./src/index.js annotated source
Back to indexIdentity function used as default values for some later iteration functions
3const identity = x => x;
4
Internally, this representation allows us to chain iterator method calls together. Most of these methods emit an object instance of Iter
itself.
8class Iter {
9
10 constructor(iterable) {
11 this.iterable = iterable;
12 }
13
Normal map over an iterator
15 map(fn) {
16 const result = [];
17 for (const member of this.iterable) {
18 result.push(fn(member));
19 }
20 return new Iter(result);
21 }
22
Normal filter from an iterator to an iterable
24 filter(fn = identity) {
25 const result = [];
26 for (const member of this.iterable) {
27 if (fn(member)) {
28 result.push(member);
29 }
30 }
31 return new Iter(result);
32 }
33
Normal left reduce over an iterator
35 reduce(fn, initial) {
36 let result = initial;
37 for (const member of this.iterable) {
38 result = fn(result, member);
39 }
40 return result;
41 }
42
Reports true if every member of the iterable evaluates to truthy value when passed into fn
45 every(fn = identity) {
46 for (const member of this.iterable) {
47 if (!fn(member)) {
48 return false;
49 }
50 }
51 return true;
52 }
53
Reports true if one or more member(s) of the iterable evaluates to truthy value when passed into fn
56 some(fn = identity) {
57 for (const member of this.iterable) {
58 if (fn(member)) {
59 return true;
60 }
61 }
62 return false;
63 }
64
Maps over an iterable and flattens each returned value from fn
with depth 1 before concatenating it into the result iterable.
67 flatMap(fn = identity) {
68 const result = this.reduce((cur, next) => cur.concat(fn(next)), []);
69 return new Iter(result);
70 }
71
Partition the list of iterable values into a list of arrays, each with max size maxSize
, in order that the members appear in the iterable. e.g. iter([1, 2, 3, 4, 5]).partition(3).toArray() == [[1, 2, 3], [4, 5]]
76 partition(maxSize) {
77 const result = [[]];
78 let idx = 0;
79 let count = 0;
80 for (const member of this.iterable) {
81 result[idx].push(member);
82 count ++;
83 if (count % maxSize === 0) {
84 result.push([]);
85 idx ++;
86 }
87 }
88 return new Iter(result);
89 }
90
Perform a non-stable sort of the iterable list values by some deterministic comparator function that takes each member and returns a value by which each member should be compared. In practice, I've found this more useful than the general comparison-based sort method in JavaScript Array.prototype.sort
.
96 sortBy(fn = identity) {
97 const result = [...this.iterable].sort((a, b) => {
98 const fnA = fn(a);
99 const fnB = fn(b);
100 if (fnA < fnB) {
101 return -1;
102 } else if (fnA > fnB) {
103 return 1;
104 } else {
105 return 0;
106 }
107 });
108 return new Iter(result);
109 }
110
Convert whatever iterable value is currently represented by the Iter
instance into a flat array.
113 toArray() {
114 return [...this.iterable];
115 }
116
An Iter
instance is also a JavaScript iterator, which means we can spread (...iter
) and for...of
loop over it.
119 [Symbol.iterator]() {
120 const iterable = this.iterable;
121 const gen = function* () {
122 for (const member of iterable) {
123 yield member;
124 }
125 }
126 return gen();
127 }
128
129}
130
Shorthand function to convert an iterator into a chainable Iter
object.
133const iter = x => new Iter(x);
134
Helper implementation of range
that takes exactly three arguments. The exposed range()
API is variadic, but that calls this with deterministic order of arguments.
138function _range(start, end, step) {
139 const result = [];
140 for (let i = start; i < end; i += step) {
141 result.push(i);
142 }
143 return result;
144}
145
range()
function whose API is identical to Python range
. Returns an Array instance.
147function range(a1, a2, a3) {
148 if (a3 === undefined) {
149 if (a2 === undefined) {
150 return _range(0, a1, 1);
151 } else {
152 return _range(a1, a2, 1);
153 }
154 } else {
155 return _range(a1, a2, a3);
156 }
157}
158
Similar to Python zip()
, zips together arrays passed in. zip()
is variadic. e.g. zip([1, 2], ['a', 'b']) => [[1, 'a'], [2, 'b']]
161function zip(...arrays) {
162 const arrayCount = arrays.length;
163 const maxLen = Math.max(...arrays.map(a => a.length));
164 const result = new Array(maxLen);
165 for (let i = 0; i < maxLen; i ++) {
166 const x = new Array(arrayCount);
167 for (let j = 0; j < arrayCount; j ++) {
168 x[j] = arrays[j][i];
169 }
170 result[i] = x;
171 }
172 return result;
173}
174
Export those APIs!
176const exposedNames = {
177 iter,
178 range,
179 zip,
180}
181if (typeof window === 'object') {
182 /* istanbul ignore next */
183 window.Ittr = exposedNames;
184}
185if (typeof module === 'object' && module.exports) {
186 module.exports = exposedNames;
187}
188
189