Apakah ada cara untuk map
/ reduce
/ filter
/ etc a Set
di JavaScript atau saya harus menulis sendiri?
Berikut ini beberapa Set.prototype
ekstensi yang masuk akal
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;
};
Mari kita ambil set kecil
let s = new Set([1,2,3,4]);
Dan beberapa fungsi kecil yang bodoh
const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;
Dan lihat bagaimana mereka bekerja
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
Bukankah itu bagus? Ya, saya juga berpikir begitu. Bandingkan dengan penggunaan iterator yang jelek
// puke
let newSet = new Set();
for (let v in s) {
newSet.add(times10(v));
}
Dan
// barf
let sum = 0;
for (let v in s) {
sum = sum + v;
}
Apakah ada cara yang lebih baik untuk menyelesaikan map
dan reduce
menggunakan Set
JavaScript?
javascript
set
ecmascript-6
reduce
Terima kasih
sumber
sumber
Set
adalah Set tidak Functors.var s = new Set([1,2,3,4]); s.map((a) => 42);
. Ini mengubah jumlah elemen, yangmap
biasanya tidak seharusnya dilakukan. Lebih buruk lagi jika Anda hanya membandingkan bagian-bagian dari objek yang disimpan, karena secara teknis itu tidak ditentukan mana yang akan Anda dapatkan.forEach
ada untuk skenario itu, tapi mengapa tidakreduce
?Jawaban:
Cara singkat untuk melakukannya adalah mengonversinya menjadi array melalui operator spread ES6.
Maka semua fungsi array tersedia untuk Anda.
sumber
Array.from
ituArray.from
berfungsi dengan TypeScript. Menggunakan[...mySet]
memberikan kesalahan:TS2461: Type 'Set<number>' is not an array type.
@@iterator
metode.ERROR TypeError: this.sausages.slice is not a function
Untuk meringkas diskusi dari komentar: sementara tidak ada alasan teknis untuk tidak memilikinya
reduce
, saat ini tidak disediakan dan kami hanya bisa berharap itu berubah dalam ES7.Adapun
map
, memanggilnya saja bisa melanggarSet
kendala, sehingga kehadirannya di sini mungkin bisa diperdebatkan.Pertimbangkan pemetaan dengan fungsi
(a) => 42
- ini akan mengubah ukuran set ke 1, dan ini mungkin atau mungkin bukan yang Anda inginkan.Jika Anda melanggar dengan itu karena misalnya Anda akan melipat, Anda dapat menerapkan
map
bagian pada setiap elemen sebelum melewati merekareduce
, sehingga menerima bahwa koleksi perantara ( yang bukan Set pada saat ini ) itu akan dikurangi mungkin memiliki elemen yang digandakan. Ini pada dasarnya setara dengan mengkonversi ke Array untuk melakukan pemrosesan.sumber
s.map(a => 42)
akan menghasilkanSet { 42 }
sehingga hasil yang dipetakan akan memiliki panjang yang berbeda tetapi tidak akan ada elemen "duplikat". Mungkin perbarui kata-katanya dan saya akan menerima jawaban ini.Penyebab kurangnya
map
/reduce
/filter
diMap
/Set
koleksi tampaknya kekhawatiran terutama konseptual. Seharusnya masing-masing jenis koleksi dalam Javascript benar-benar menentukan metode iteratif sendiri hanya untuk memungkinkan inidari pada
Alternatifnya adalah menentukan peta / perkecil / filter sebagai bagian dari protokol iterable / iterator, karena
entries
/values
/keys
kembaliIterator
s. Bisa dibayangkan bahwa tidak semua iterable juga "bisa dipetakan". Alternatif lain adalah menentukan "protokol pengumpulan" yang terpisah untuk tujuan ini.Namun, saya tidak tahu diskusi saat ini tentang topik ini di ES.
sumber