假设我们有一张地图:let m = new Map();
,使用m.values()
返回一个地图迭代器。
但我不能在该迭代器上使用forEach()
或map()
,并且在迭代器上实现while循环似乎是反模式,因为ES6提供了像map()
这样的函数。
那么有没有办法在迭代器上使用map()
?
执行此操作的最简单且性能最差的方法是:
Array.from(m).map(([key,value]) => /* whatever */)
更好
Array.from(m, ([key, value]) => /* whatever */))
Array.from
采用任何可迭代或类似数组的东西并将其转换为数组!正如丹尼尔在评论中指出的那样,我们可以在转换中添加映射函数以删除迭代,然后是中间数组。
正如@hraban在评论中指出的那样,使用Array.from
将你的表现从O(1)
转移到O(n)
。由于m
是Map
,它们不能无限,我们不必担心无限序列。对于大多数情况,这就足够了。
还有其他几种循环遍历地图的方法。
forEach
m.forEach((value,key) => /* stuff */ )
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
您可以定义另一个迭代器函数来循环遍历:
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(','));
现在您可能会问:为什么不使用Array.from
呢?因为这将遍历整个迭代器,将其保存到(临时)数组,再次迭代它然后执行映射。如果列表很大(甚至可能是无限的),这将导致不必要的内存使用。
当然,如果项目列表相当小,使用Array.from
应该绰绰有余。
这种最简单,最高效的方法是使用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']
此方法适用于任何非无限可迭代。并且它避免了必须单独调用Array.from(map).map(...)
,它会迭代迭代两次并且性能更差。
您可以在iterable上检索迭代器,然后返回另一个迭代器,该迭代器在每个迭代元素上调用映射回调函数。
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
您可以使用itiriri为迭代实现类似数组的方法:
import { query } from 'itiriri';
let m = new Map();
// set map ...
query(m).filter([k, v] => k < 10).forEach([k, v] => console.log(v));
let arr = query(m.values()).map(v => v * 10).toArray();
迭代地图
1)迭代地图键
Map提供了我们可以用来迭代所有键的keys()方法。
for (const k of m.keys()) {
console.log(k)
}
2)迭代地图值
Map对象提供了我们可以用来迭代所有值的values()方法:
for (const v of m.values()) {
console.log(v)
}
3)迭代映射键,值对
Map对象提供了我们可以用来迭代所有值的entries()方法:
for (const [k, v] of m.entries()) {
console.log(k, v)
}
我们也可以简化为
for (const [k, v] of m) {
console.log(k, v)
}