Javascript 在迭代器上使用 map()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43885365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using map() on an iterator
提问by shinzou
Say we have a Map: let m = new Map();, using m.values()returns a map iterator.
假设我们有一个 Map: let m = new Map();,使用m.values()返回一个映射迭代器。
But I can't use forEach()or map()on that iterator and implementing a while loop on that iterator seems like an anti-pattern since ES6 offer functions like map().
但是我不能在那个迭代器上使用forEach()or 并且map()在那个迭代器上实现一个 while 循环似乎是一种反模式,因为 ES6 提供了像map().
So is there a way to use map()on an iterator?
那么有没有办法map()在迭代器上使用?
采纳答案by ktilcu
The simplestand least performantway to do this is:
执行此操作的最简单且性能最低的方法是:
Array.from(m).map(([key,value]) => /* whatever */)
Better yet
更好
Array.from(m, ([key, value]) => /* whatever */))
Array.fromtakes any iterable or array-like thing and converts it into an array! As Daniel points out in the comments, we can add a mapping function to the conversion to remove an iteration and subsequently an intermediate array.
Array.from接受任何可迭代或类似数组的东西并将其转换为数组!正如 Daniel 在评论中指出的那样,我们可以向转换添加一个映射函数,以删除迭代和随后的中间数组。
Using Array.fromwill move your performance from O(1)to O(n)as @hraban points out in the comments. Since mis a Map, and they can't be infinite, we don't have to worry about an infinite sequence. For most instances, this will suffice.
正如@hraban 在评论中指出的那样,使用Array.from将使您的表现从O(1)到O(n)。由于m是 a Map,而且它们不可能是无限的,我们不必担心无限序列。在大多数情况下,这就足够了。
There are a couple of other ways to loop through a map.
还有其他几种方法可以遍历地图。
Using forEach
使用 forEach
m.forEach((value,key) => /* stuff */ )
Using for..of
使用 for..of
var myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');
for (var [key, value] of myMap) {
console.log(key + ' = ' + value);
}
// 0 = zero
// 1 = one
回答by sheean
You could define another iterator function to loop over this:
您可以定义另一个迭代器函数来循环:
function* generator() {
for(let i = 0; i < 10; i++) {
console.log(i);
yield i;
}
}
function* mapIterator(iterator, mapping) {
while (true) {
let result = iterator.next();
if (result.done) {
break;
}
yield mapping(result.value);
}
}
let values = generator();
let mapped = mapIterator(values, (i) => {
let result = i*2;
console.log(`x2 = ${result}`);
return result;
});
console.log('The values will be generated right now.');
console.log(Array.from(mapped).join(','));
Now you might ask: why not just use Array.frominstead? Because this will run through the entire iterator, save it to a (temporary) array, iterate it again and thendo the mapping. If the list is huge (or even potentially infinite) this will lead to unnecessary memory usage.
现在你可能会问:为什么不直接使用Array.from呢?因为这会贯穿整个迭代器,将其保存到(临时)数组中,再次迭代,然后进行映射。如果列表很大(甚至可能是无限的),这将导致不必要的内存使用。
Of course, if the list of items is fairly small, using Array.fromshould be more than sufficient.
当然,如果项目列表相当少,使用Array.from应该绰绰有余。
回答by Ian Storm Taylor
This simplest and most performant way is to use the second argument to Array.fromto achieve this:
这种最简单、最高效的方法是使用第二个参数Array.from来实现:
const map = new Map()
map.set('a', 1)
map.set('b', 2)
Array.from(map, ([key, value]) => `${key}:${value}`)
// ['a:1', 'b:2']
This approach works for any non-infiniteiterable. And it avoids having to use a separate call to Array.from(map).map(...)which would iterate through the iterable twice and be worse for performance.
这种方法适用于任何非无限迭代。并且它避免了必须使用单独的调用,Array.from(map).map(...)该调用会遍历可迭代对象两次并且性能更差。
回答by MartyO256
You could retrieve an iterator over the iterable, then return another iterator that calls the mapping callback function on each iterated element.
您可以检索迭代器上的迭代器,然后返回另一个迭代器,该迭代器在每个迭代元素上调用映射回调函数。
const map = (iterable, callback) => {
return {
[Symbol.iterator]() {
const iterator = iterable[Symbol.iterator]();
return {
next() {
const r = iterator.next();
if (r.done)
return r;
else {
return {
value: callback(r.value),
done: false,
};
}
}
}
}
}
};
// Arrays are iterable
console.log(...map([0, 1, 2, 3, 4], (num) => 2 * num)); // 0 2 4 6 8
回答by kataik
Take a look at https://www.npmjs.com/package/fluent-iterable
看看https://www.npmjs.com/package/fluent-iterable
Works with all of iterables (Map, generator function, array) and async iterables.
适用于所有可迭代对象(Map、生成器函数、数组)和异步可迭代对象。
const map = new Map();
...
console.log(fluent(map).filter(..).map(..));

