3484
|
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 |
map(callback) {
|
|
41 |
const result = [];
|
|
42 |
for (const element of this) {
|
|
43 |
result.push(callback(element));
|
|
44 |
}
|
|
45 |
|
|
46 |
return result;
|
|
47 |
}
|
|
48 |
|
|
49 |
filter(callback) {
|
|
50 |
const result = [];
|
|
51 |
for (const element of this) {
|
|
52 |
if (callback(element)) {
|
|
53 |
result.push(element);
|
|
54 |
}
|
|
55 |
}
|
|
56 |
|
|
57 |
return result;
|
|
58 |
}
|
|
59 |
|
|
60 |
reduce(callback, initialValue) {
|
|
61 |
let empty = typeof initialValue === 'undefined';
|
|
62 |
let accumulator = initialValue;
|
|
63 |
let index = 0;
|
|
64 |
for (const currentValue of this) {
|
|
65 |
if (empty) {
|
|
66 |
accumulator = currentValue;
|
|
67 |
empty = false;
|
|
68 |
continue;
|
|
69 |
}
|
|
70 |
|
|
71 |
accumulator = callback(accumulator, currentValue, index, this);
|
|
72 |
index++;
|
|
73 |
}
|
|
74 |
|
|
75 |
if (empty) {
|
|
76 |
throw new TypeError('Reduce of empty Iterator with no initial value');
|
|
77 |
}
|
|
78 |
|
|
79 |
return accumulator;
|
|
80 |
}
|
|
81 |
|
|
82 |
some(callback) {
|
|
83 |
for (const element of this) {
|
|
84 |
if (callback(element)) {
|
|
85 |
return true;
|
|
86 |
}
|
|
87 |
}
|
|
88 |
|
|
89 |
return false;
|
|
90 |
}
|
|
91 |
|
|
92 |
every(callback) {
|
|
93 |
for (const element of this) {
|
|
94 |
if (!callback(element)) {
|
|
95 |
return false;
|
|
96 |
}
|
|
97 |
}
|
|
98 |
|
|
99 |
return true;
|
|
100 |
}
|
|
101 |
|
|
102 |
static fromIterable(iterable) {
|
|
103 |
return new Iterator(function * () {
|
|
104 |
for (const element of iterable) {
|
|
105 |
yield element;
|
|
106 |
}
|
|
107 |
});
|
|
108 |
}
|
|
109 |
|
|
110 |
toArray() {
|
|
111 |
return Array.from(this);
|
|
112 |
}
|
|
113 |
|
|
114 |
next() {
|
|
115 |
if (!this.currentInvokedGenerator) {
|
|
116 |
this.currentInvokedGenerator = this[Symbol.iterator]();
|
|
117 |
}
|
|
118 |
|
|
119 |
return this.currentInvokedGenerator.next();
|
|
120 |
}
|
|
121 |
|
|
122 |
reset() {
|
|
123 |
delete this.currentInvokedGenerator;
|
|
124 |
}
|
|
125 |
}
|
|
126 |
|
|
127 |
function rangeSimple(stop) {
|
|
128 |
return new Iterator(function * () {
|
|
129 |
for (let i = 0; i < stop; i++) {
|
|
130 |
yield i;
|
|
131 |
}
|
|
132 |
});
|
|
133 |
}
|
|
134 |
|
|
135 |
function rangeOverload(start, stop, step = 1) {
|
|
136 |
return new Iterator(function * () {
|
|
137 |
for (let i = start; i < stop; i += step) {
|
|
138 |
yield i;
|
|
139 |
}
|
|
140 |
});
|
|
141 |
}
|
|
142 |
|
|
143 |
function range(...args) {
|
|
144 |
if (args.length < 2) {
|
|
145 |
return rangeSimple(...args);
|
|
146 |
}
|
|
147 |
|
|
148 |
return rangeOverload(...args);
|
|
149 |
}
|
|
150 |
|
|
151 |
function enumerate(iterable) {
|
|
152 |
return new Iterator(function * () {
|
|
153 |
let index = 0;
|
|
154 |
for (const element of iterable) {
|
|
155 |
yield [index, element];
|
|
156 |
index++;
|
|
157 |
}
|
|
158 |
});
|
|
159 |
}
|
|
160 |
|
|
161 |
const _zip = longest => (...iterables) => {
|
|
162 |
if (iterables.length < 2) {
|
|
163 |
throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given");
|
|
164 |
}
|
|
165 |
|
|
166 |
return new Iterator(function * () {
|
|
167 |
const iterators = iterables.map(iterable => Iterator.fromIterable(iterable));
|
|
168 |
while (true) {
|
|
169 |
const row = iterators.map(iterator => iterator.next());
|
|
170 |
const check = longest ? row.every.bind(row) : row.some.bind(row);
|
|
171 |
if (check(next => next.done)) {
|
|
172 |
return;
|
|
173 |
}
|
|
174 |
|
|
175 |
yield row.map(next => next.value);
|
|
176 |
}
|
|
177 |
});
|
|
178 |
};
|
|
179 |
|
|
180 |
const zip = _zip(false), zipLongest= _zip(true);
|
|
181 |
|
|
182 |
function items(obj) {
|
|
183 |
let {keys, get} = obj;
|
|
184 |
if (obj instanceof Map) {
|
|
185 |
keys = keys.bind(obj);
|
|
186 |
get = get.bind(obj);
|
|
187 |
} else {
|
|
188 |
keys = function () {
|
|
189 |
return Object.keys(obj);
|
|
190 |
};
|
|
191 |
|
|
192 |
get = function (key) {
|
|
193 |
return obj[key];
|
|
194 |
};
|
|
195 |
}
|
|
196 |
|
|
197 |
return new Iterator(function * () {
|
|
198 |
for (const key of keys()) {
|
|
199 |
yield [key, get(key)];
|
|
200 |
}
|
|
201 |
});
|
|
202 |
}
|
|
203 |
|
|
204 |
/*
|
|
205 |
module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items};
|
|
206 |
*/
|