如何过滤 JavaScript 地图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48707227/
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
How to filter a JavaScript Map?
提问by Philipp Cla?en
Given an ES6 Mapand predicate function, how do I safely delete all non-matching elements for the map?
给定 ES6 Map和 predicate 函数,如何安全地删除地图的所有不匹配元素?
I could not find an official API function, but I can think of two implementations. The first does not attempt to delete in-place, but instead creates a copy:
我找不到官方的 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' ] ]"
The other deletes in-place. In my tests, it works but I did not find a guarantee that modifying a map does not break the iterator (of the for-of loop):
另一个就地删除。在我的测试中,它有效,但我没有发现修改映射不会破坏迭代器(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' ] ]"
Question:
题:
- Is the second version (the in-place delete) correct on all platforms?
- Is there a better way to implement an in-place filter? Maybe some official API that I missed?
- 第二个版本(就地删除)在所有平台上都正确吗?
- 有没有更好的方法来实现就地过滤器?也许我错过了一些官方 API?
采纳答案by Estus Flask
ES6 iterables have no problems when an entry is deleted inside a loop.
当在循环内删除条目时,ES6 可迭代对象没有问题。
There is no special API that would allow to efficiently filter ES6 map entries without iterating over them.
没有特殊的 API 可以有效地过滤 ES6 映射条目而不对其进行迭代。
If a map doesn't have to be immutable and should be modified in-place, creating a new map on filtering provides overhead.
如果地图不必是不可变的并且应该就地修改,则在过滤时创建新地图会提供开销。
There is also Map forEach, but it presumes that value will be used, too.
还有 Map forEach,但它假定 value 也会被使用。
Since the map is being filtered only by its key, there's no use for entry object. It can be improved by iterating over map keys:
由于地图仅通过其键进行过滤,因此条目对象没有用。可以通过迭代映射键来改进它:
for (let k of map.keys()) {
if (!(k % 2))
map.delete(k);
}
回答by Roman
If we want to use .filter()iterator, we can apply a simple trick, because there is no .filter operator for ES6 Maps.The approach from Dr. Axel Rauschmayeris:
如果我们想使用.filter()迭代器,我们可以应用一个简单的技巧,因为 ES6 Maps 没有 .filter 运算符。Axel Rauschmayer 博士的方法是:
- Convert the map into an array of [key,value] pairs.
- Map or filter the array.
- Convert the result back to a map.
- 将映射转换为 [key,value] 对的数组。
- 映射或过滤数组。
- 将结果转换回地图。
Example:
例子:
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]]
回答by GaddMaster
An elegant answer which I learned.
我学到的一个优雅的答案。
// MAP EXAMPLE
const myMap = new Map();
myMap.set("1G7JA", {
id: 1,
name: "Hyman"
});
myMap.set("1G7JB", {
id: 2,
name: "Betty"
});
myMap.set("1G7JC", {
id: 3,
name: "Mary"
});
// CONVERT MAP TO ARRAY
let userID = "ABCDE";
const myArray = Map.values(myMap).filter(report => report.user._id === userID);
// CONVERT ARRAY TO MAP
const setArrayToMap = (array, element) => {
const myMap = new Map();
array.forEach(item => {
myMap.set(item[element.toString()], item);
});
return myMap;
};
However, you are converting a map into an array (Lot of processing) simple to filter. It's counterproductive, only use on small arrays, where the need to retain your list as an object out weight the reason to use this.
但是,您正在将地图转换为易于过滤的数组(大量处理)。它适得其反,仅用于小数组,其中需要保留您的列表作为对象的权重是使用它的原因。
Regards
问候
Daniel
丹尼尔

