Javascript: Map, Reduce ve Filter – Bölüm 1
İlk olarak 2011 yılında karşımıza çıkan “map”, “filter”, “reduce” metotları, diziler ile işlem yaparken daha performanslı , daha okunabilir kodlar yazmamıza olanak veriyor.
Dört bölümlük yazı dizimde, bu kahramanların (Avengers) öykülerinden bahsedeceğim. Birinci bölüm map()
, ikinci bölüm filter()
ve üçüncü bölüm reduce()
hakkında olacak. Finali ise kahramanlarımızın kesişen hayatlarından bahsedeceğim. Lafı fazla uzatmadan başlayalım.
map(): Son Dizi Bükücü
Javascript dokümanında ise map()
şu şekilde tanımlanıyor.
“Dizinin her bir elemanı için; parametre olarak verilen (callback) fonksiyonu çağırır ve fonksiyonda belirtilen işlemlere göre yeni bir dizi(array) oluşturur.”
Söz Dizimi:
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
Parametreler:
callback
: Dizinin her bir elemanı için çağrılacak olan fonksiyondur. Üç parametre alır. Fonksiyonun ilk parametresi olan currentValue dizinin o anda işlem yapılan elemanı, ikinci parametresi olan index dizinin o anda işlem yapılan elemanın indeksi ve üçüncü parametresi olan array ise map tarafında çağrılan dizidir. currentValue parametresi zorunlu olarak callback fonksiyonuna verilmeli, diğer parametreler isteğe bağlı olarak; verilebilir yada verilmeyebilir.thisArg
: callback fonksiyonu çalıştırılırken kullanacağı this değeridir.
map()
konusunda örneklere geçmeden önce yukarıda anlatılan parametrelerin map() içinde hangi değerleri aldığına 4 farklı örnek bakalım.
Hatırlatma: Aşağıdaki ilk dört örnekte gösterilen thisArg parametresinin kullanım mantığı thisArg parametresini alan tüm fonksiyonlarda da aynıdır.
Örnek-1: “kullaniciAdi” değişkeni thisArg
olarak atanıyor. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const listMapHakkinda = [ {'id': 1, 'adi': 'Ahmet', 'yas': 35, 'maaş': '1000'}, {'id': 2, 'adi': 'Ayşe', 'yas': 30, 'maaş': '1300'}]; const kullaniciTipi = 'admin'; console.log('\n1. ÖRNEK: thisArgs paramtere kullanımı: kullaniciTipi parametresi değişken olarak atanıyor'); const yeniDizi1 = listMapHakkinda.map(function callback(currentValue, index, array) { console.log( '\n~index parametre değeri: ' + index + '\n~currentValue parametre değeri: ' + JSON.stringify(currentValue) + '\n~array parametre değeri: ' + JSON.stringify(array) + '\n~thisArg parametre değeri: ' + this); }, kullaniciTipi); |
Örnek-2: thisArg
parametresine herhangi bir değer atanmıyor. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
const listMapHakkinda = [ {'id': 1, 'adi': 'Ahmet', 'yas': 35, 'maaş': '1000'}, {'id': 2, 'adi': 'Ayşe', 'yas': 30, 'maaş': '1300'}]; let kullaniciTipi = 'admin'; console.log('\n2. ÖRNEK: thisArgs paramtere kullanımı: parametre geçilmiyor'); const yeniDizi2 = listMapHakkinda.map(function callback(currentValue, index, array) { console.log( '\n~thisArg parametre değeri: ' + this); console.log( '\n~dışardaki kullaniciTipi nin callback içinde kullanımı : ' + kullaniciTipi); }); |
Örnek-3: thisArg
parametresine yeni bir obje atanıyor. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const listMapHakkinda = [ {'id': 1, 'adi': 'Ahmet', 'yas': 35, 'maaş': '1000'}, {'id': 2, 'adi': 'Ayşe', 'yas': 30, 'maaş': '1300'}]; let kullaniciTipi = 'admin'; console.log('\n3. ÖRNEK: thisArgs paramtere kullanımı: {tip: kullaniciTipi, tarih: new Date()}'); const yeniDizi3 = listMapHakkinda.map(function callback(currentValue, index, array) { console.log( '\n~thisArg parametre değeri: ' + JSON.stringify(this) + '\n~thisArg içindeki TİP parametre değeri: ' + this.tip + '\n~thisArg içindeki TARİH parametre değeri: ' + this.tarih ); }, {tip: kullaniciTipi, tarih: new Date()}); |
Örnek-4: thisArg
parametresine array atanıyor. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
const listMapHakkinda = [ {'id': 1, 'adi': 'Ahmet', 'yas': 35, 'maaş': '1000'}, {'id': 2, 'adi': 'Ayşe', 'yas': 30, 'maaş': '1300'}]; let kullaniciTipi = 'admin'; console.log('\n4. ÖRNEK: thisArgs paramtere kullanımı: Array gönderimi'); const yeniDizi4 = listMapHakkinda.map(function callback(currentValue, index, array) { for (const sayi of this) { console.log(sayi); } }, [1, 2]); |
Uzun bir girişten sonra konumuza dönüp, map()
’in gücünü ve yeteneklerini örneklerle görelim.
Örnek-1: Eleman sayısı 10000 olan ve 0 ile 10000 arasında rastgele sayılardan oluşan bir dizi oluşturup; dizi içinde tek sayı olan elamanın yerine ‘tek’, çift sayı olan elemanın yerine ‘çift’ yazalım. ([5,46,13] →[‘tek’, ‘çift’, ‘tek’]). Aynı işlemi ‘for’
döngüsü ile yapıp hız testi yapalım. Denemek için burayı tıklayın
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
const rastgeleListe = Array.from({length: 10000}, () => Math.floor(Math.random() * 10000)); let t1 = performance.now(); let tempList = rastgeleListe.map(x => { return x % 2 === 0 ? 'çift' : 'tek'; }); let t2 = performance.now(); console.log("map sonuç süre:"+(t2-t1).toFixed(5)); tempList = []; t1 = performance.now(); for (const x of rastgeleListe) { tempList.push(x % 2 === 0 ? 'çift' : 'tek'); } rastgeleListeFor = JSON.stringify(tempList); t2 = performance.now(); console.log("for sonuç süre:"+(t2-t1).toFixed(5)); console.log(tempList); |
Bundan sonraki örneklerde aşağıdaki kisiler
dizisi kullanılacaktır ve “for” kullanılmayacaktır.
1 2 3 4 5 6 7 8 9 10 11 |
<strong class="markup--strong markup--pre-strong">const </strong>kisiler = [ {<strong class="markup--strong markup--pre-strong">id</strong>: 1, <strong class="markup--strong markup--pre-strong">adi</strong>: <strong class="markup--strong markup--pre-strong">'Ahmet'</strong>, <strong class="markup--strong markup--pre-strong">soyadi</strong>: <strong class="markup--strong markup--pre-strong">'Yüksekseslekonuşma'</strong>, <strong class="markup--strong markup--pre-strong">yas</strong>: 15, <strong class="markup--strong markup--pre-strong">cinsiyet</strong>: <strong class="markup--strong markup--pre-strong">'Erkek'</strong>, <strong class="markup--strong markup--pre-strong">unvan</strong>: <strong class="markup--strong markup--pre-strong">'Öğrenci'</strong>, <strong class="markup--strong markup--pre-strong">puan</strong>: 65}, {<strong class="markup--strong markup--pre-strong">id</strong>: 2, <strong class="markup--strong markup--pre-strong">adi</strong>: <strong class="markup--strong markup--pre-strong">'Sultan'</strong>, <strong class="markup--strong markup--pre-strong">soyadi</strong>: <strong class="markup--strong markup--pre-strong">'Hayvanlarısev'</strong>, <strong class="markup--strong markup--pre-strong">yas</strong>: 32, <strong class="markup--strong markup--pre-strong">cinsiyet</strong>: <strong class="markup--strong markup--pre-strong">'Kadın'</strong>, <strong class="markup--strong markup--pre-strong">unvan</strong>: <strong class="markup--strong markup--pre-strong">'Öğretmen'</strong>, <strong class="markup--strong markup--pre-strong">puan</strong>: 75}, {<strong class="markup--strong markup--pre-strong">id</strong>: 3, <strong class="markup--strong markup--pre-strong">adi</strong>: <strong class="markup--strong markup--pre-strong">'Hatice'</strong>, <strong class="markup--strong markup--pre-strong">soyadi</strong>: <strong class="markup--strong markup--pre-strong">'Çimenlerebasma'</strong>, <strong class="markup--strong markup--pre-strong">yas</strong>: 26, <strong class="markup--strong markup--pre-strong">cinsiyet</strong>: <strong class="markup--strong markup--pre-strong">'Kadın'</strong>, <strong class="markup--strong markup--pre-strong">unvan</strong>: <strong class="markup--strong markup--pre-strong">'Doktor'</strong>, <strong class="markup--strong markup--pre-strong">puan</strong>: 85}, {<strong class="markup--strong markup--pre-strong">id</strong>: 4, <strong class="markup--strong markup--pre-strong">adi</strong>: <strong class="markup--strong markup--pre-strong">'Ali'</strong>, <strong class="markup--strong markup--pre-strong">soyadi</strong>: <strong class="markup--strong markup--pre-strong">'Yerleretükürme'</strong>, <strong class="markup--strong markup--pre-strong">yas</strong>: 26, <strong class="markup--strong markup--pre-strong">cinsiyet</strong>: <strong class="markup--strong markup--pre-strong">'Erkek'</strong>, <strong class="markup--strong markup--pre-strong">unvan</strong>: <strong class="markup--strong markup--pre-strong">'İşçi'</strong>, <strong class="markup--strong markup--pre-strong">puan</strong>: 75}, {<strong class="markup--strong markup--pre-strong">id</strong>: 5, <strong class="markup--strong markup--pre-strong">adi</strong>: <strong class="markup--strong markup--pre-strong">'Kamuran'</strong>, <strong class="markup--strong markup--pre-strong">soyadi</strong>: <strong class="markup--strong markup--pre-strong">'Kurallarauy'</strong>, <strong class="markup--strong markup--pre-strong">yas</strong>: 52, <strong class="markup--strong markup--pre-strong">cinsiyet</strong>: <strong class="markup--strong markup--pre-strong">'Kadın'</strong>, <strong class="markup--strong markup--pre-strong">unvan</strong>: <strong class="markup--strong markup--pre-strong">'Hemşire'</strong>, <strong class="markup--strong markup--pre-strong">puan</strong>: 85} ]; |
Örnek-2: Kişiler dizisinde 30 yaşın üzerinde olan kişilerin puanlarına 10 puan ekleyelim. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const kisiler = [ {id: 1, adi: 'Ahmet', soyadi: 'Yüksekseslekonuşma', yas: 15, cinsiyet: 'Erkek', unvan: 'Öğrenci', puan: 65}, {id: 2, adi: 'Sultan', soyadi: 'Hayvanlarısev', yas: 32, cinsiyet: 'Kadın', unvan: 'Öğretmen', puan: 75}, {id: 3, adi: 'Hatiçe', soyadi: 'Çimenlerebasma', yas: 26, cinsiyet: 'Kadın', unvan: 'Doktor', puan: 85}, {id: 4, adi: 'Ali', soyadi: 'Yerleretükürme', yas: 26, cinsiyet: 'Erkek', unvan: 'İşçi', puan: 75}, {id: 4, adi: 'Kamuran', soyadi: 'Kurallarauy', yas: 52, cinsiyet: 'Kadın', unvan: 'Hemşilre', puan: 85} ]; const yeniPuanlar1 = kisiler.map(x => { x.puan = x.yas > 30 ? x.puan + 10 : x.puan; return x; } ); console.log(yeniPuanlar1); // 26 yaşında olanlara 1 puan ekleyelim const yeniPuanlar2 = kisiler.map(p => p.yas !== 26 ? p : {...p, puan: p.p + 1}); console.log(yeniPuanlar2); |
Örnek-3: Kişiler dizisinden sadece adi ve soyadından oluşan yeni bir dizi oluşturalım. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const kisiler = [ {id: 1, adi: 'Ahmet', soyadi: 'Yüksekseslekonuşma', yas: 15, cinsiyet: 'Erkek', unvan: 'Öğrenci', puan: 65}, {id: 2, adi: 'Sultan', soyadi: 'Hayvanlarısev', yas: 32, cinsiyet: 'Kadın', unvan: 'Öğretmen', puan: 75}, {id: 3, adi: 'Hatiçe', soyadi: 'Çimenlerebasma', yas: 26, cinsiyet: 'Kadın', unvan: 'Doktor', puan: 85}, {id: 4, adi: 'Ali', soyadi: 'Yerleretükürme', yas: 26, cinsiyet: 'Erkek', unvan: 'İşçi', puan: 75}, {id: 4, adi: 'Kamuran', soyadi: 'Kurallarauy', yas: 52, cinsiyet: 'Kadın', unvan: 'Hemşilre', puan: 85} ]; const yeniliste = kisiler.map(e => ({adi:e.adi, soyadi:e.soyadi})); console.log(yeniliste); |
Örnek-4: Kişiler dizisinde cinsiyet bilgisine göre tekil liste oluşturalım. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const kisiler = [ {id: 1, adi: 'Ahmet', soyadi: 'Yüksekseslekonuşma', yas: 15, cinsiyet: 'Erkek', unvan: 'Öğrenci', puan: 65}, {id: 2, adi: 'Sultan', soyadi: 'Hayvanlarısev', yas: 32, cinsiyet: 'Kadın', unvan: 'Öğretmen', puan: 75}, {id: 3, adi: 'Hatiçe', soyadi: 'Çimenlerebasma', yas: 26, cinsiyet: 'Kadın', unvan: 'Doktor', puan: 85}, {id: 4, adi: 'Ali', soyadi: 'Yerleretükürme', yas: 26, cinsiyet: 'Erkek', unvan: 'İşçi', puan: 75}, {id: 5, adi: 'Kamuran', soyadi: 'Kurallarauy', yas: 52, cinsiyet: 'Kadın', unvan: 'Hemşire', puan: 85} ]; const cinsiyetler= [...new Set(kisiler.map(x => x.cinsiyet))]; console.log(cinsiyetler); |
Örnek-5: { ‘a’: 1, ‘b’: 2, ‘c’: 3 }
nesnesinin tüm elemanlarını 5 ile çarpalım. Dikkat ilgili nesne bir dizi değil. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 9 10 |
let listeOlmayanNesne = { 'key1': 5, 'key2': 10, 'key3': 15 }; Object.keys(listeOlmayanNesne).map(function(key, index) { listeOlmayanNesne[key] *= 5; }); console.log(listeOlmayanNesne); |
Örnek-6: {k1: “say”, k2: “my”, k3: “name(!)”} nesnesinden cümle yapalım. Dikkat ilgili nesne bir dizi değil. Denemek için burayı tıklayınız
1 2 3 4 5 6 7 8 |
const listeOlmayanNesne = {k1: "say", k2: "my", k3: "name(!)"}; const cumle = Object.entries(listeOlmayanNesne).map( p => p[1] ).join(' '); console.log(cumle); |
Örnek-7: “Say My Name(!)” kelimesini dizi yapalım. Denemek için burayı tıklayınız.
1 2 3 4 5 6 7 8 9 10 |
const map = Array.prototype.map; const yeniListe = map.call('Say My Name (!)', function(x) { return x; }); console.log(yeniListe) |
Örnek-8: Dizinin sadece belirli elemanlarını parametre olarak geçme. Denemek için burayı tıklayınız. map()
’in içinden “key2” kullanılırsa kod hata alacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const liste = [ {key1:1, key2:2,key3:3}, {key1:4, key2:5,key3:6}, {key1:7, key2:8,key3:9} ]; const yeniListe= liste.map(({key1, key3}) => key1+key3); console.log(yeniListe); |
Örnek-9: Key, Value bilgisi verilen bir diziden yeni bir dizi yapalım. Denemek için burayı tıklayınız. kaynak
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var liste = [{key: "adi", value: "Ahmet"}, {key: "adi", value: "Ayşe"}, {key: "adi", value: "Soner"}]; var yeniListe = liste.map(p =>{ var tempObj = {}; tempObj[p.key] = p.value; return tempObj; }); console.log(yeniListe) |
Örnek-10: [1, 4, 9] sayıların karekökünü alalım. Denemek için burayı tıklayınız. kaynak
1 2 3 4 5 6 7 |
const sayilar = [1, 4, 9]; const kareKok = sayilar.map(Math.sqrt); console.log(kareKok); |
map()
çok güçlü bir metot. Kullandıkça seveceksiniz. Bir sonraki bölümde filter()
ile tanışacağız. Sonraki bölümde görüşmek üzere.