JavaScriptでmap
/reduce
/filter
/etc a 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
を使用してreduce
およびSet
を実現するより良い方法はありますか?
簡単な方法は、ES6スプレッド演算子を使用して配列に変換することです。
その後、すべての配列関数が使用可能になります。
const mySet = new Set([1,2,3,4]);
[...mySet].reduce()
コメントからの議論を要約すると:notに設定する技術的な理由はありませんが、reduce
がありますが、現在提供されていないため、 ES7で変更されることを願っています。
map
に関しては、それを単独で呼び出すとSet
制約に違反する可能性があるため、その存在は議論の余地があるかもしれません。
関数(a) => 42
を使用したマッピングを検討してください。セットのサイズが1に変更されますが、これはまたはそうでないかもしれません。
あなたがそれを違反しても大丈夫なら、例えばとにかく折りたたむので、map
に渡す直前にすべての要素にreduce
部分を適用して、中間コレクション(これはSetではないこの点)削減される予定の要素が重複している可能性があります。これは、処理を行うために配列に変換することと本質的に同等です。
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]));
代替手段は、entries
/values
/keys
がIterator
sを返すため、map/reduce/filterをiterable/iteratorプロトコルの一部として指定することでした。ただし、すべての反復可能要素が「マッピング可能」ではないことも考えられます。別の選択肢は、このまさに目的のために別個の「収集プロトコル」を指定することでした。
しかし、ESでのこのトピックに関する現在の議論は知りません。