如何在 JavaScript 中映射/减少/过滤 Set?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33234666/
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 map/reduce/filter a Set in JavaScript?
提问by Thank you
Is there any way to map
/reduce
/filter
/etc a Set
in JavaScript or will I have to write my own?
有没有办法在 JavaScript 中map
/ reduce
/ filter
/etc aSet
或者我必须自己编写?
Here's some sensible Set.prototype
extensions
这是一些合理的Set.prototype
扩展
Set.prototype.map = function map(f) {
var newSet = new Set();
for (var v of this.values()) newSet.add(f(v));
return newSet;
};
Set.prototype.reduce = function(f,initial) {
var result = initial;
for (var v of this) result = f(result, v);
return result;
};
Set.prototype.filter = function filter(f) {
var newSet = new Set();
for (var v of this) if(f(v)) newSet.add(v);
return newSet;
};
Set.prototype.every = function every(f) {
for (var v of this) if (!f(v)) return false;
return true;
};
Set.prototype.some = function some(f) {
for (var v of this) if (f(v)) return true;
return false;
};
Let's take a little set
让我们来一组
let s = new Set([1,2,3,4]);
And some stupid little functions
还有一些愚蠢的小功能
const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;
And see how they work
看看它们是如何工作的
s.map(times10); //=> Set {10,20,30,40}
s.reduce(add, 0); //=> 10
s.filter(even); //=> Set {2,4}
s.every(even); //=> false
s.some(even); //=> true
Isn't that nice ? Yeah, I think so too. Compare that to the ugly iterator usage
这不是很好吗?是的,我也这么认为。将其与丑陋的迭代器用法进行比较
// puke
let newSet = new Set();
for (let v in s) {
newSet.add(times10(v));
}
And
和
// barf
let sum = 0;
for (let v in s) {
sum = sum + v;
}
Is there any better way to accomplish map
and reduce
using a Set
in JavaScript?
有没有更好的方法来完成map
和reduce
使用Set
JavaScript 中的 a?
回答by ZephDavies
A short-hand way to do it is to convert it to an array via the ES6 spread operator.
一种简单的方法是通过 ES6 扩展运算符将其转换为数组。
Then all the array functions are available to you.
然后所有数组函数都可供您使用。
const mySet = new Set([1,2,3,4]);
[...mySet].reduce()
回答by Bartek Banachewicz
To sum up the discussion from comments: while there are no technical reasons for set to nothave reduce
, it's not currently provided and we can only hope it changes in ES7.
总结评论中的讨论:虽然没有技术原因 set to nothave reduce
,但目前没有提供,我们只能希望它在 ES7 中有所改变。
As for map
, calling it alone could violate the Set
constraint, so its presence here might be debatable.
至于map
,单独调用它可能会违反Set
约束,因此它在这里的存在可能值得商榷。
Consider mapping with a function (a) => 42
- it will change the set's size to 1, and this might or might notbe what you wanted.
考虑使用函数映射(a) => 42
- 它会将集合的大小更改为 1,这可能是您想要的,也可能不是。
If you're ok with violating that because e.g. you're going to fold anyway, you can apply the map
part on every element just before passing them to reduce
, thus accepting that the intermediate collection (which isn't a Set at this point) that's going to be reduced might have duplicated elements. This is essentially equivalent to converting to Array to do processing.
如果你同意违反它,因为例如你无论如何都要折叠,你可以map
在将它们传递给之前将部件应用到每个元素上reduce
,从而接受中间集合(此时不是 Set)是将要减少可能有重复的元素。这本质上相当于转换为Array来做处理。
回答by Bartek Banachewicz
The cause of the lack of map
/reduce
/filter
on Map
/Set
collections seem to be mainly conceptual concerns. Should each collection type in Javascript actually specify its own iterative methods only to allow this
缺乏的原因map
/ reduce
/filter
上Map
/Set
收藏似乎是主要概念的关注。Javascript 中的每个集合类型是否应该实际指定自己的迭代方法只允许这样做
const mySet = new Set([1,2,3]);
const myMap = new Map([[1,1],[2,2],[3,3]]);
mySet.map(x => x + 1);
myMap.map(([k, x]) => [k, x + 1]);
instead of
代替
new Set(Array.from(mySet.values(), x => x + 1));
new Map(Array.from(myMap.entries(), ([k, x]) => [k, x + 1]));
An alternative were to specify map/reduce/filter as part of the iterable/iterator protocol, since entries
/values
/keys
return Iterator
s. It is conceivable though that not every iterable is also "mappable". Another alternative were to specify a separate "collection protocol" for this very purpose.
一种替代是,以指定映射/降低/过滤器可迭代/迭代器协议的一部分,因为entries
/ values
/keys
回报Iterator
秒。可以想象,并非每个可迭代对象也是“可映射的”。另一种选择是为此目的指定一个单独的“收集协议”。
However, I do not know the current discussion on this topic at ES.
但是,我不知道 ES 目前关于这个话题的讨论。