如何过滤JavaScript Map?

时间:2018-02-09 13:42:20

标签: javascript ecmascript-6

鉴于ES6 Map和谓词函数,如何安全地删除地图的所有非匹配元素?

我找不到官方的API函数,但我可以想到两个实现。第一个不会尝试就地删除,而是创建一个副本:



// version 1:
function filter(map, pred) {
  const result = new Map();
  for (let [k, v] of map) {
    if (pred(k,v)) {
      result.set(k, v);
    }
  }
  return result;
}

const map = new Map().set(1,"one").set(2,"two").set(3,"three");
const even = filter(map, (k,v) => k % 2 === 0);
console.log([...even]); // Output: "[ [ 2, 'two' ] ]"




其他人就地删除。在我的测试中,它可以工作,但我没有找到保证修改映射不会破坏迭代器(for-of循环):



// version 2:
function deleteIfNot(map, pred) {
  for (let [k, v] of map) {
    if (!pred(k,v)) {
      map.delete(k);
    }
  }
  return map;
}

const map = new Map().set(1,"one").set(2,"two").set(3,"three");
deleteIfNot(map, (k,v) => k % 2 === 0);
console.log([...map]); // Output: "[ [ 2, 'two' ] ]"




问题:

  • 所有平台上的第二个版本(就地删除)是否正确?
  • 有没有更好的方法来实现就地过滤器?也许我错过了一些官方API?

3 个答案:

答案 0 :(得分:5)

在循环中删除条目时,ES6 iterables没有问题。

没有特殊的API可以有效地过滤ES6地图条目而无需迭代它们。

如果地图不必是不可变的并且应该就地修改,那么在过滤时创建新地图会产生开销。

还有Map forEach,但它也假设也会使用该值。

由于地图仅通过其键进行过滤,因此对入口对象没有用处。可以通过迭代映射键来改进它:

for (let k of map.keys()) {
  if (!(k % 2))
    map.delete(k);
}

答案 1 :(得分:5)

如果我们要使用 .filter()迭代器,我们可以应用一个简单的技巧,因为ES6 Maps没有.filter运算符。Dr. Axel Rauschmayer的方法是:< / p>

  • 将地图转换为[key,value]对数组。
  • 映射或过滤数组。
  • 将结果转换回地图。

示例:

const map0 = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

const map1 = new Map(
  [...map0]
  .filter(([k, v]) => v < 3 )
);

console.info([...map1]) //[0: ["a", 1], 1: ["b", 2]]

答案 2 :(得分:1)

我学到的一个优雅的答案。

const reports = Object.values(reportArray).filter(report=> report.user._id === userId);

但是,您正在将地图转换为易于过滤的数组(很多处理)。这适得其反,仅用于小型数组,在这种情况下,需要将列表作为对象保留下来,这是使用此数组的原因。

致谢

丹尼尔