Saya ingin memfilter berbagai item dengan menggunakan map()
fungsi tersebut. Berikut ini potongan kode:
var filteredItems = items.map(function(item)
{
if( ...some condition... )
{
return item;
}
});
Masalahnya adalah bahwa item yang disaring masih menggunakan ruang dalam array dan saya ingin menghapusnya sepenuhnya.
Ada ide?
EDIT: Terima kasih, saya lupa filter()
, yang saya inginkan sebenarnya adalah filter()
a map()
.
EDIT2: Terima kasih telah menunjukkannya map()
dan filter()
tidak diterapkan di semua browser, meskipun kode khusus saya tidak dimaksudkan untuk dijalankan di browser.
javascript
functional-programming
data-manipulation
client-side
Vincent Robert
sumber
sumber
Jawaban:
Anda harus menggunakan
filter
metode daripada peta kecuali Anda ingin mengubah item dalam larik, selain pemfilteran.misalnya.
var filteredItems = items.filter(function(item) { return ...some condition...; });
[Sunting: Tentu saja Anda selalu dapat melakukan
sourceArray.filter(...).map(...)
untuk memfilter dan bermutasi]sumber
map
tidak bermutasimap
.x=[1,2,3];y = x.map(z => z*2);console.log(x,y);
Terinspirasi dengan menulis jawaban ini, saya akhirnya memperluas dan menulis posting blog yang membahas ini dengan cermat. Saya sarankan untuk memeriksanya jika Anda ingin mengembangkan pemahaman yang lebih dalam tentang bagaimana memikirkan masalah ini - saya mencoba menjelaskannya sepotong demi sepotong, dan juga memberikan perbandingan JSperf di akhir, membahas pertimbangan kecepatan.
Artinya, tl; dr adalah ini: Untuk mencapai apa yang Anda minta (pemfilteran dan pemetaan dalam satu panggilan fungsi), Anda akan menggunakan
Array.reduce()
.Namun, pendekatan 2 yang lebih mudah dibaca dan (kurang penting) biasanya secara signifikan lebih cepat 2 adalah dengan menggunakan filter dan peta yang dirangkai bersama:
[1,2,3].filter(num => num > 2).map(num => num * 2)
Berikut ini adalah penjelasan tentang cara
Array.reduce()
kerja, dan bagaimana hal itu dapat digunakan untuk menyelesaikan filter dan memetakan dalam satu iterasi. Sekali lagi, jika ini terlalu padat, saya sangat menyarankan untuk melihat posting blog yang ditautkan di atas, yang merupakan pengantar yang jauh lebih ramah dengan contoh dan perkembangan yang jelas.Anda memberikan pengurangan argumen yang merupakan fungsi (biasanya anonim).
Fungsi anonim itu mengambil dua parameter - satu (seperti fungsi anonim yang diteruskan ke map / filter / forEach) adalah iterasi yang akan dioperasikan. Ada argumen lain untuk fungsi anonim yang diteruskan untuk mengurangi, bagaimanapun, bahwa fungsi tersebut tidak menerima, dan itu adalah nilai yang akan diteruskan di antara pemanggilan fungsi, yang sering disebut sebagai memo .
Perhatikan bahwa sementara Array.filter () hanya mengambil satu argumen (fungsi), Array.reduce () juga membutuhkan argumen kedua yang penting (meskipun opsional): nilai awal untuk 'memo' yang akan diteruskan ke fungsi anonim itu sebagai argumen pertama, dan selanjutnya dapat dimutasi dan diteruskan di antara pemanggilan fungsi. (Jika tidak diberikan, maka 'memo' dalam pemanggilan fungsi anonim pertama secara default akan menjadi iterasi pertama, dan argumen 'iteratee' sebenarnya akan menjadi nilai kedua dalam larik)
Dalam kasus kami, kami akan mengirimkan array kosong untuk memulai, dan kemudian memilih apakah akan menyuntikkan iteratee kami ke dalam array kami atau tidak berdasarkan fungsi kami - ini adalah proses pemfilteran.
Akhirnya, kita akan mengembalikan 'array in progress' kita pada setiap pemanggilan fungsi anonim, dan reduce akan mengambil nilai kembali itu dan meneruskannya sebagai argumen (disebut memo) ke pemanggilan fungsi berikutnya.
Hal ini memungkinkan filter dan peta terjadi dalam satu iterasi, mengurangi setengah dari jumlah iterasi yang diperlukan - hanya melakukan pekerjaan dua kali lebih banyak setiap iterasi, jadi tidak ada yang benar-benar disimpan selain panggilan fungsi, yang tidak terlalu mahal dalam javascript .
Untuk penjelasan yang lebih lengkap, lihat dokumen MDN (atau posting saya yang direferensikan di awal jawaban ini).
Contoh dasar panggilan Reduce:
let array = [1,2,3]; const initialMemo = []; array = array.reduce((memo, iteratee) => { // if condition is our filter if (iteratee > 1) { // what happens inside the filter is the map memo.push(iteratee * 2); } // this return value will be passed in as the 'memo' argument // to the next call of this function, and this function will have // every element passed into it at some point. return memo; }, initialMemo) console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]
versi yang lebih ringkas:
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
Perhatikan bahwa iterasi pertama tidak lebih besar dari satu, sehingga difilter. Perhatikan juga initialMemo, yang diberi nama hanya untuk memperjelas keberadaannya dan menarik perhatian padanya. Sekali lagi, ini diteruskan sebagai 'memo' ke pemanggilan fungsi anonim pertama, dan kemudian nilai yang dikembalikan dari fungsi anonim diteruskan sebagai argumen 'memo' ke fungsi berikutnya.
Contoh lain dari kasus penggunaan klasik untuk memo akan mengembalikan angka terkecil atau terbesar dalam sebuah array. Contoh:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val) // ^this would return the largest number in the list.
Contoh bagaimana menulis fungsi reduce Anda sendiri (ini sering membantu memahami fungsi seperti ini, saya temukan):
test_arr = []; // we accept an anonymous function, and an optional 'initial memo' value. test_arr.my_reducer = function(reduceFunc, initialMemo) { // if we did not pass in a second argument, then our first memo value // will be whatever is in index zero. (Otherwise, it will // be that second argument.) const initialMemoIsIndexZero = arguments.length < 2; // here we use that logic to set the memo value accordingly. let memo = initialMemoIsIndexZero ? this[0] : initialMemo; // here we use that same boolean to decide whether the first // value we pass in as iteratee is either the first or second // element const initialIteratee = initialMemoIsIndexZero ? 1 : 0; for (var i = initialIteratee; i < this.length; i++) { // memo is either the argument passed in above, or the // first item in the list. initialIteratee is either the // first item in the list, or the second item in the list. memo = reduceFunc(memo, this[i]); // or, more technically complete, give access to base array // and index to the reducer as well: // memo = reduceFunc(memo, this[i], i, this); } // after we've compressed the array into a single value, // we return it. return memo; }
Implementasi sebenarnya memungkinkan akses ke hal-hal seperti indeks, misalnya, tetapi saya harap ini membantu Anda mendapatkan gambaran yang tidak rumit tentang intinya.
sumber
reduce
adalah, tidak sepertifilter
+map
, callback bisa melewati argumen indeks yang merupakan indeks dari larik asli, dan bukan yang difilter.Bukan itu yang dilakukan peta. Anda benar-benar menginginkan Array.filter . Atau jika Anda benar-benar ingin menghapus elemen dari daftar asli, Anda harus melakukannya secara imperatif dengan loop for.
sumber
Metode Array Filter
var arr = [1, 2, 3] // ES5 syntax arr = arr.filter(function(item){ return item != 3 }) // ES2015 syntax arr = arr.filter(item => item != 3) console.log( arr )
sumber
var arr = [1,2,"xxx", "yyy"]; arr = arr.filter(function(e){ return e!="xxx" }) console.log(arr)
Namun Anda harus mencatat bahwa
Array.filter
tidak didukung di semua browser jadi, Anda harus membuat prototipe://This prototype is provided by the Mozilla foundation and //is distributed under the MIT license. //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license if (!Array.prototype.filter) { Array.prototype.filter = function(fun /*, thisp*/) { var len = this.length; if (typeof fun != "function") throw new TypeError(); var res = new Array(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) { var val = this[i]; // in case fun mutates this if (fun.call(thisp, val, i, this)) res.push(val); } } return res; }; }
Dan dengan melakukan itu, Anda dapat membuat prototipe metode apa pun yang mungkin Anda perlukan.
sumber
Pernyataan berikut membersihkan objek menggunakan fungsi peta.
var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}]; arraytoclean.map((x,i)=>x.toberemoved=undefined); console.dir(arraytoclean);
sumber
Saya baru saja menulis persimpangan array yang menangani dengan benar juga duplikat
https://gist.github.com/gkucmierz/8ee04544fa842411f7553ef66ac2fcf0
// array intersection that correctly handles also duplicates const intersection = (a1, a2) => { const cnt = new Map(); a2.map(el => cnt[el] = el in cnt ? cnt[el] + 1 : 1); return a1.filter(el => el in cnt && 0 < cnt[el]--); }; const l = console.log; l(intersection('1234'.split``, '3456'.split``)); // [ '3', '4' ] l(intersection('12344'.split``, '3456'.split``)); // [ '3', '4' ] l(intersection('1234'.split``, '33456'.split``)); // [ '3', '4' ] l(intersection('12334'.split``, '33456'.split``)); // [ '3', '3', '4' ]
sumber
Pertama, Anda dapat menggunakan peta dan dengan rantai Anda dapat menggunakan filter
state.map(item => { if(item.id === action.item.id){ return { id : action.item.id, name : item.name, price: item.price, quantity : item.quantity-1 } }else{ return item; } }).filter(item => { if(item.quantity <= 0){ return false; }else{ return true; } });
sumber