Reputation: 1675
What's the correct way of using the new ES5 array functions with ES6 generators? Do I have to explicitly convert the iterable into an array first, or is there a better way? For example:
function* range(low, high) {
var i = low;
while(i < high)
yield i++;
}
// Sum of numbers in range, doesn't work
console.log(range(0, 10).reduce((x,y) => x + y));
Upvotes: 10
Views: 1733
Reputation:
Build the array using Array.from
:
console.log(Array.from(range(0, 10)).reduce((x,y) => x + y));
Array.from
creates an array from an iterable. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from.
If you want to do the reduce without creating the array, then you'll end up needing to do something like:
var sum = 0;
for (e of range(0, 10)) sum += e;
Upvotes: 5
Reputation: 30330
Generator functions return Iterator objects. The Iterator API does not include higher order Array methods such as map
, reduce
etc, so you need to build an intermediate Array (or use a library like wu.js).
You can use the spread operator to concisely build an Array from a (finite) iterator:
var sum = [...range(0, 10)].reduce((e, i) => e + i)
Upvotes: 10
Reputation: 18530
Since Array.from
does not work on Chrome at the current time, I needed another way to convert an Iterator into an Array.
(though of course you can shim it with a polyfill)
function iterator2Array(iterator) {
var result = [];
for (var item in iterator) {
result.push(item)
}
return result;
}
For similar reasons I add a "toArray" to the prototype of a Map so that I basically convert an iterator into an Array so that you can use its functional-oriented methods; of course each item of the array will be a [key, value] tuple (exactly like in its Map.entries()
)
if (!Map.prototype.toArray) {
/**
* Transforms a map into an Array of 'tuples' [[key, value], ...]
*/
Map.prototype.toArray = function () {
var result = [];
for (var item of this) {
result.push(item);
}
return result;
}
}
var m = new Map([[0, 0], ['a', 'A']]);
m.toArray()
Then you can use it as an array - remember the [key, value] approach though!
m.toArray().map(
function(item, index, array) {
var key = item[0],
value = item[1];
console.log(key + ": " + value);
return value;
});
This will return the values of the map (ok not superuseful of course!)
If you prefer a more standar looking loop:
var i = iterator.entries(),
result = [],
value;
while (value = i.next().value) {
result.push(value);
}
Upvotes: 3