是否有任何方法来映射/减少/过滤/等一个集在JavaScript或我必须写我自己?

这里有一些明智的集合。模型的扩展

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

And

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

有什么更好的方法来完成映射和减少使用一个集在JavaScript?


当前回答

const set = new Set([1,2,3,4,5]);

function filterSet(index) {
    set.delete([...set][index]);
}

filterSet(3); // Set { 1, 2, 3, 5, [size]: 4 }

我认为这是一个相当不错的“过滤”集合的解决方案。

其他回答

const set = new Set([1,2,3,4,5]);

function filterSet(index) {
    set.delete([...set][index]);
}

filterSet(3); // Set { 1, 2, 3, 5, [size]: 4 }

我认为这是一个相当不错的“过滤”集合的解决方案。

一种简便的方法是通过ES6展开操作符将其转换为数组。

然后所有的数组函数都可用。

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

map/ Set集合上缺少map/reduce/filter的原因似乎主要是概念上的问题。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协议的一部分,因为条目/值/键返回iterator。可以想象,并不是每个可迭代对象都是“可映射的”。另一种选择是为此目的指定一个单独的“收集协议”。

然而,我不知道ES目前对这个话题的讨论情况。

总结一下评论中的讨论:虽然没有技术原因导致set没有reduce功能,但目前还没有提供,我们只希望在ES7中会有所改变。

至于map,单独调用它可能违反Set约束,因此它在这里的存在可能是有争议的。

考虑使用函数(a) => 42进行映射——它将把集合的大小更改为1,这可能是也可能不是您想要的。

如果你不介意违反这个规则,比如你无论如何都要折叠,你可以在将每个元素传递给reduce之前应用map部分,从而接受将要被reduce的中间集合(此时不是Set)可能有重复的元素。这本质上等同于转换到Array来进行处理。