如何在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:49:03  来源:igfitidea点击:

How to map/reduce/filter a Set in JavaScript?

javascriptsetecmascript-6reduce

提问by Thank you

Is there any way to map/reduce/filter/etc a Setin JavaScript or will I have to write my own?

有没有办法在 JavaScript 中map/ reduce/ filter/etc aSet或者我必须自己编写?

Here's some sensible Set.prototypeextensions

这是一些合理的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 mapand reduceusing a Setin JavaScript?

有没有更好的方法来完成mapreduce使用SetJavaScript 中的 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 Setconstraint, 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 mappart 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/filteron Map/Setcollections seem to be mainly conceptual concerns. Should each collection type in Javascript actually specify its own iterative methods only to allow this

缺乏的原因map/ reduce/filterMap/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/keysreturn Iterators. 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 目前关于这个话题的讨论。