author | Edouard Tisserant <edouard@beremiz.fr> |
Fri, 30 Aug 2024 11:50:23 +0200 | |
changeset 4008 | f30573e98600 |
parent 3594 | 30f7eade322f |
permissions | -rw-r--r-- |
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 |
||
3485
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
40 |
forEach(callback) { |
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
41 |
for (const element of this) { |
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
42 |
callback(element); |
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
43 |
} |
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
44 |
} |
5f417d3c2d03
SVGHMI: Add forEach to local copy of pythonic.js
Edouard Tisserant
parents:
3484
diff
changeset
|
45 |
|
3484 | 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) => { |
|
3594
30f7eade322f
SVGHMI: add support for "enable expressions" with arbitrary variable name assignment.
Edouard Tisserant
parents:
3485
diff
changeset
|
168 |
if (iterables.length == 0) { |
30f7eade322f
SVGHMI: add support for "enable expressions" with arbitrary variable name assignment.
Edouard Tisserant
parents:
3485
diff
changeset
|
169 |
// works starting with 1 iterable |
30f7eade322f
SVGHMI: add support for "enable expressions" with arbitrary variable name assignment.
Edouard Tisserant
parents:
3485
diff
changeset
|
170 |
// [a,b,c] -> [[a],[b],[c]] |
30f7eade322f
SVGHMI: add support for "enable expressions" with arbitrary variable name assignment.
Edouard Tisserant
parents:
3485
diff
changeset
|
171 |
// [a,b,c],[d,e,f] -> [[a,d],[b,e],[c,f]] |
30f7eade322f
SVGHMI: add support for "enable expressions" with arbitrary variable name assignment.
Edouard Tisserant
parents:
3485
diff
changeset
|
172 |
throw new TypeError("zip takes 1 iterables at least, "+iterables.length+" given"); |
3484 | 173 |
} |
174 |
||
175 |
return new Iterator(function * () { |
|
176 |
const iterators = iterables.map(iterable => Iterator.fromIterable(iterable)); |
|
177 |
while (true) { |
|
178 |
const row = iterators.map(iterator => iterator.next()); |
|
179 |
const check = longest ? row.every.bind(row) : row.some.bind(row); |
|
180 |
if (check(next => next.done)) { |
|
181 |
return; |
|
182 |
} |
|
183 |
||
184 |
yield row.map(next => next.value); |
|
185 |
} |
|
186 |
}); |
|
187 |
}; |
|
188 |
||
189 |
const zip = _zip(false), zipLongest= _zip(true); |
|
190 |
||
191 |
function items(obj) { |
|
192 |
let {keys, get} = obj; |
|
193 |
if (obj instanceof Map) { |
|
194 |
keys = keys.bind(obj); |
|
195 |
get = get.bind(obj); |
|
196 |
} else { |
|
197 |
keys = function () { |
|
198 |
return Object.keys(obj); |
|
199 |
}; |
|
200 |
||
201 |
get = function (key) { |
|
202 |
return obj[key]; |
|
203 |
}; |
|
204 |
} |
|
205 |
||
206 |
return new Iterator(function * () { |
|
207 |
for (const key of keys()) { |
|
208 |
yield [key, get(key)]; |
|
209 |
} |
|
210 |
}); |
|
211 |
} |
|
212 |
||
213 |
/* |
|
214 |
module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items}; |
|
215 |
*/ |