如何在JavaScript中映射/缩小/过滤Set?

时间:2015-10-20 10:50:28

标签: javascript set ecmascript-6 reduce

JavaScript中有map / reduce / filter / etc和Set的任何方式,还是我必须自己编写?

这里有一些明智的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 = new Set([1,2,3,4]);

还有一些愚蠢的小功能

const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;

看看它们是如何运作的

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
  

不是很好吗?是的,我也这么认为。将其与丑陋的迭代器用法进行比较

// puke
let newSet = new Set();
for (let v in s) {
  newSet.add(times10(v));
}

// barf
let sum = 0;
for (let v in s) {
  sum = sum + v;
}

有没有更好的方法在JavaScript中使用map完成reduceSet

3 个答案:

答案 0 :(得分:64)

一种简单的方法是通过ES6扩展运算符将其转换为数组。

然后您可以使用所有数组函数。

const mySet = new Set([1,2,3,4]);
[...mySet].reduce()

答案 1 :(得分:19)

总结评论中的讨论:虽然没有技术原因设置为reduce,但它目前尚未提供,我们只能希望它发生变化在ES7中。

对于map,单独调用它可能会违反Set约束,因此它的存在可能存在争议。

考虑使用函数(a) => 42进行映射 - 它会将集合的大小更改为1,这可能或者可能不是

如果你违反了这个,那就是无论如何你都要弃去,你可以在将map部分传递给reduce之前将其应用于每个元素,从而接受中间集合(不是' ta在此时设置)将要减少的可能有重复的元素。这基本上等同于转换为Array来进行处理。

答案 2 :(得分:6)

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]);

而不是

new Set(Array.from(mySet.values(), x => x + 1));
new Map(Array.from(myMap.entries(), ([k, x]) => [k, x + 1]));

另一种方法是将map / reduce / filter指定为iterable / iterator协议的一部分,因为entries / values / keys返回Iterator s。可以想象,并非每个可迭代的也是可映射的#34;。另一种选择是指定一个单独的收集协议"为了这个目的。

但是,我不知道ES目前关于这个主题的讨论。