svghmi/pythonic.js
branchwxPython4
changeset 3491 88c4b18453d5
parent 3485 5f417d3c2d03
child 3594 30f7eade322f
equal deleted inserted replaced
3483:e25f1cf69df9 3491:88c4b18453d5
       
     1 /*
       
     2 
       
     3 From https://github.com/keyvan-m-sadeghi/pythonic
       
     4 
       
     5 Slightly modified in order to be usable in browser (i.e. not as a node.js module)
       
     6 
       
     7 The MIT License (MIT)
       
     8 
       
     9 Copyright (c) 2016 Assister.Ai
       
    10 
       
    11 Permission is hereby granted, free of charge, to any person obtaining a copy of
       
    12 this software and associated documentation files (the "Software"), to deal in
       
    13 the Software without restriction, including without limitation the rights to
       
    14 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
       
    15 the Software, and to permit persons to whom the Software is furnished to do so,
       
    16 subject to the following conditions:
       
    17 
       
    18 The above copyright notice and this permission notice shall be included in all
       
    19 copies or substantial portions of the Software.
       
    20 
       
    21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
       
    23 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
       
    24 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
       
    25 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
    26 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
    27 */
       
    28 
       
    29 class Iterator {
       
    30     constructor(generator) {
       
    31         this[Symbol.iterator] = generator;
       
    32     }
       
    33 
       
    34     async * [Symbol.asyncIterator]() {
       
    35         for (const element of this) {
       
    36             yield await element;
       
    37         }
       
    38     }
       
    39 
       
    40     forEach(callback) {
       
    41         for (const element of this) {
       
    42             callback(element);
       
    43         }
       
    44     }
       
    45 
       
    46     map(callback) {
       
    47         const result = [];
       
    48         for (const element of this) {
       
    49             result.push(callback(element));
       
    50         }
       
    51 
       
    52         return result;
       
    53     }
       
    54 
       
    55     filter(callback) {
       
    56         const result = [];
       
    57         for (const element of this) {
       
    58             if (callback(element)) {
       
    59                 result.push(element);
       
    60             }
       
    61         }
       
    62 
       
    63         return result;
       
    64     }
       
    65 
       
    66     reduce(callback, initialValue) {
       
    67         let empty = typeof initialValue === 'undefined';
       
    68         let accumulator = initialValue;
       
    69         let index = 0;
       
    70         for (const currentValue of this) {
       
    71             if (empty) {
       
    72                 accumulator = currentValue;
       
    73                 empty = false;
       
    74                 continue;
       
    75             }
       
    76 
       
    77             accumulator = callback(accumulator, currentValue, index, this);
       
    78             index++;
       
    79         }
       
    80 
       
    81         if (empty) {
       
    82             throw new TypeError('Reduce of empty Iterator with no initial value');
       
    83         }
       
    84 
       
    85         return accumulator;
       
    86     }
       
    87 
       
    88     some(callback) {
       
    89         for (const element of this) {
       
    90             if (callback(element)) {
       
    91                 return true;
       
    92             }
       
    93         }
       
    94 
       
    95         return false;
       
    96     }
       
    97 
       
    98     every(callback) {
       
    99         for (const element of this) {
       
   100             if (!callback(element)) {
       
   101                 return false;
       
   102             }
       
   103         }
       
   104 
       
   105         return true;
       
   106     }
       
   107 
       
   108     static fromIterable(iterable) {
       
   109         return new Iterator(function * () {
       
   110             for (const element of iterable) {
       
   111                 yield element;
       
   112             }
       
   113         });
       
   114     }
       
   115 
       
   116     toArray() {
       
   117         return Array.from(this);
       
   118     }
       
   119 
       
   120     next() {
       
   121         if (!this.currentInvokedGenerator) {
       
   122             this.currentInvokedGenerator = this[Symbol.iterator]();
       
   123         }
       
   124 
       
   125         return this.currentInvokedGenerator.next();
       
   126     }
       
   127 
       
   128     reset() {
       
   129         delete this.currentInvokedGenerator;
       
   130     }
       
   131 }
       
   132 
       
   133 function rangeSimple(stop) {
       
   134     return new Iterator(function * () {
       
   135         for (let i = 0; i < stop; i++) {
       
   136             yield i;
       
   137         }
       
   138     });
       
   139 }
       
   140 
       
   141 function rangeOverload(start, stop, step = 1) {
       
   142     return new Iterator(function * () {
       
   143         for (let i = start; i < stop; i += step) {
       
   144             yield i;
       
   145         }
       
   146     });
       
   147 }
       
   148 
       
   149 function range(...args) {
       
   150     if (args.length < 2) {
       
   151         return rangeSimple(...args);
       
   152     }
       
   153 
       
   154     return rangeOverload(...args);
       
   155 }
       
   156 
       
   157 function enumerate(iterable) {
       
   158     return new Iterator(function * () {
       
   159         let index = 0;
       
   160         for (const element of iterable) {
       
   161             yield [index, element];
       
   162             index++;
       
   163         }
       
   164     });
       
   165 }
       
   166 
       
   167 const _zip = longest => (...iterables) => {
       
   168     if (iterables.length < 2) {
       
   169         throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given");
       
   170     }
       
   171 
       
   172     return new Iterator(function * () {
       
   173         const iterators = iterables.map(iterable => Iterator.fromIterable(iterable));
       
   174         while (true) {
       
   175             const row = iterators.map(iterator => iterator.next());
       
   176             const check = longest ? row.every.bind(row) : row.some.bind(row);
       
   177             if (check(next => next.done)) {
       
   178                 return;
       
   179             }
       
   180 
       
   181             yield row.map(next => next.value);
       
   182         }
       
   183     });
       
   184 };
       
   185 
       
   186 const zip = _zip(false), zipLongest= _zip(true);
       
   187 
       
   188 function items(obj) {
       
   189     let {keys, get} = obj;
       
   190     if (obj instanceof Map) {
       
   191         keys = keys.bind(obj);
       
   192         get = get.bind(obj);
       
   193     } else {
       
   194         keys = function () {
       
   195             return Object.keys(obj);
       
   196         };
       
   197 
       
   198         get = function (key) {
       
   199             return obj[key];
       
   200         };
       
   201     }
       
   202 
       
   203     return new Iterator(function * () {
       
   204         for (const key of keys()) {
       
   205             yield [key, get(key)];
       
   206         }
       
   207     });
       
   208 }
       
   209 
       
   210 /*
       
   211 module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items};
       
   212 */