Is there any way to map/reduce/filter/etc a Set in JavaScript or will I have to write my own?
Here's some sensible Set.prototype extensions
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?
Setis that Sets aren't Functors.var s = new Set([1,2,3,4]); s.map((a) => 42);. It changes the number of elements, whichmaptypically isn't supposed to do. Even worse if you're only comparing parts of the kept objects, because then technically it's unspecified which one you'll get.forEachexists for that scenario, but why noreducethen ?