在迭代器上使用map()

问题描述 投票:50回答:6

假设我们有一张地图:let m = new Map();,使用m.values()返回一个地图迭代器。

但我不能在该迭代器上使用forEach()map(),并且在迭代器上实现while循环似乎是反模式,因为ES6提供了像map()这样的函数。

那么有没有办法在迭代器上使用map()

javascript dictionary syntax ecmascript-6 iterator
6个回答
45
投票

执行此操作的最简单且性能最差的方法是:

Array.from(m).map(([key,value]) => /* whatever */)

更好

Array.from(m, ([key, value]) => /* whatever */))

Array.from采用任何可迭代或类似数组的东西并将其转换为数组!正如丹尼尔在评论中指出的那样,我们可以在转换中添加映射函数以删除迭代,然后是中间数组。

正如@hraban在评论中指出的那样,使用Array.from将你的表现从O(1)转移到O(n)。由于mMap,它们不能无限,我们不必担心无限序列。对于大多数情况,这就足够了。

还有其他几种循环遍历地图的方法。

使用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

13
投票

您可以定义另一个迭代器函数来循环遍历:

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应该绰绰有余。


3
投票

这种最简单,最高效的方法是使用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(...),它会迭代迭代两次并且性能更差。


1
投票

您可以在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

0
投票

您可以使用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
投票

迭代地图

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)
}
© www.soinside.com 2019 - 2024. All rights reserved.