鉴于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' ] ]"

问题:
答案 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>
示例:
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);
但是,您正在将地图转换为易于过滤的数组(很多处理)。这适得其反,仅用于小型数组,在这种情况下,需要将列表作为对象保留下来,这是使用此数组的原因。
致谢
丹尼尔