Ashraf Latif

Back

2018-01-15

Fahami Asas .foreach(), .filter(), .map(), .sort(), & .reduce() Javascript

Hari ni aku nak buat nota sedikit mengenai function-function di dalam functional programming JavaScript. Kita akan gunakan data ni dalam semua contoh kita.

const companies = [
  { name: "Malayan Banking", category: "Finance", start: 1981, end: 2004 },
  { name: "Lazada", category: "Retail", start: 1992, end: 2008 },
  { name: "Proton", category: "Auto", start: 1999, end: 2007 },
  { name: "Shopee", category: "Retail", start: 1989, end: 2010 },
  {
    name: "Bangkit Technology",
    category: "Technology",
    start: 2009,
    end: 2014,
  },
  { name: "CIMB Bank", category: "Finance", start: 1987, end: 2010 },
  { name: "Perodua", category: "Auto", start: 1986, end: 1996 },
  { name: "Komrad Ventures", category: "Technology", start: 2011, end: 2016 },
  { name: "Lelong", category: "Retail", start: 1981, end: 1989 },
]

const ages = [33, 12, 20, 16, 5, 54, 21, 44, 61, 13, 15, 45, 25, 64, 32]

FOREACH()

Rujukan: foreach

Function .foreEach() adalah function yang memudahkan kita untuk loop array. Kebiasaannya kita akan loop array menggunakan for loop. Contohnya:

for (let i = 0; i < companies.length; i++) {
  console.log(companies[i].name)
}

/* 
"Malayan Banking"
"Lazada"
"Proton"
"Shopee"
"Bangkit Technology"
"CIMB Bank"
"Perodua"
"Komrad Ventures"
"Lelong"
*/

Untuk loop menggunakan function .forEach() kita perlu gunakannya dengan callback function:

companies.forEach(function(company) {
  console.log(company.name)
})

// simplified with es6 arrow function

companies.forEach(company => console.log(company.name))

/* 
"Malayan Banking"
"Lazada"
"Proton"
"Shopee"
"Bangkit Technology"
"CIMB Bank"
"Perodua"
"Komrad Ventures"
"Lelong"
*/

Perhatikan syntax yang lebih ringkas (malah boleh lebih ringkas dengan syntax es6 arrow function) dan keputusan yang sama.

FILTER()

Rujukan: filter

Function .filter() pula digunakan untuk “filter” array dan pulangkan keputusan yang di “filter”. misalnya:

const over18 = ages.filter(age => age > 18)

console.log(over18) // [33, 20, 54, 21, 44, 61, 45, 25, 64, 32];

Syntax yang pendek kan? Cuba lihat kalau kita gunakan for loop untuk filter array seringkas ini.

const over18 = []
for (let i = 0; i < ages.length; i++) {
  if (ages[i] > 18) {
    over18.push(ages[i])
  }
}

console.log(over18) // [33, 20, 54, 21, 44, 61, 45, 25, 64, 32];

Jom filter array objek, misalnya kita nak tahu company yang kekal sekurang-kurangnya 20 tahun.

const company20tahun = companies.filter(
  company => company.end - company.start >= 20
)

console.log(company20tahun)
/*
{ category: "Finance", end: 2004, name: "Malayan Banking", start: 1981 },
{ category: "Retail", end: 2010, name: "Shopee", start: 1989 },
{ category: "Finance", end: 2010, name: "CIMB Bank", start: 1987 }
*/

MAP()

Rujukan: map

Function .map() ni sebenarnya lebih kurang fungsinya seperti function .forEach() sebab dia loop through each element array tu. Tapi tak sama macam .forEach() sebab .map() akan create array baharu. cuba tengok contoh ni.

// forEach()
const foreach = ages.forEach(a => a + 1)
console.log(foreach) // undefined

// map()
const map = ages.map(a => a + 1)
console.log(map) // [34, 13, 21, 17, 6, 55, 22, 45, 62, 14, 16, 46, 26, 65, 33]

Disebabkan .map() boleh create array baharu, kita boleh gunakannya dengan function lain seperti .filter() misalnya. kita ambil contoh filter di atas (company sekurang-kurangnya kekal 20 tahun). Dan aku nak introduce es6 template string sekali.

const company20tahun = companies
  .filter(c => c.end - c.start > 20)
  .map(c => c.name)

console.log(company20tahun) // ["Malayan Banking", "Shopee", "CIMB Bank"]

// es6 template string

const company20tahunES6ts = companies
  .filter(c => c.end - c.start > 20)
  .map(c => {
    return `${c.name} from ${c.start} to ${c.end}`
  })

console.log(company20tahunES6ts) // ["Malayan Banking from 1981 to 2004", "Shopee from 1989 to 2010", "CIMB Bank from 1987 to 2010"]

Contoh lain adalah seperti ini

const sesaja = ages.map(age => Math.sqrt(age)).map(age => Math.pow(age, 3))

console.log(sesaja)
// [189.57056733575496, 41.56921938165305, 89.4427190999916, 64, 11.18033988749895, 396.81733833087486, 96.23408959407264, 291.8629815512752, 476.42523023030583, 46.872166581031856, 58.09475019311126, 301.86917696247167, 125, 512, 181.0193359837562]

SORT()

Rujukan: sort

Sort, nampak seperti mudah. Tetapi banyak faktor perlu diambil kira misalnya Unicode point order. Kenapa aku cakap macam tu? cuba tengok contoh ni:

const sortSimple = ages.sort()

console.log(sortSimple)
// [12, 13, 15, 16, 20, 21, 25, 32, 33, 44, 45, 5, 54, 61, 64]\

Lihat, di dalam array tersebut nombor 5 tidak berada di hadapan sekali, kenapa? Ini kerana dalam Unicode point order, nombor seperti 12 dan lain-lain adalah hasil gabungan nombor 1 dan 2, menjadikan dia 12. Dalam kes ini, nombor 5 dianggap gabungan 5 dan 0. Contoh lain jika kita sort array ini [1,2,12,14,15].sort() jawapannya adalah 1,12,14,15,2 . Untuk mendapatkan jawapan yang lebih tepat dalam konteks ini, kita perlu menggunakan compareFunction seperti ini:

const sort = ages.sort((a, b) => {
  if (a > b) {
    return 1
  } else {
    return -1
  }
})

console.log(sort) // [5, 12, 13, 15, 16, 20, 21, 25, 32, 33, 44, 45, 54, 61, 64]

Lihat dengan cara ini 5 tersusun tepat pada kedudukan yang sepatutnya. Alternatifnya boleh ditulis begini:

// Ascending
const simpleSortAsc = ages.sort((a, b) => a - b)

console.log(simpleSortAsc) // [5, 12, 13, 15, 16, 20, 21, 25, 32, 33, 44, 45, 54, 61, 64]

// Descending
const simpleSortDesc = ages.sort((a, b) => b - a)

console.log(simpleSortDesc) // [64, 61, 54, 45, 44, 33, 32, 25, 21, 20, 16, 15, 13, 12, 5]

Ini pula penggunaan .sort() untuk menyusun objek dalam array.

const companyStartYear = companies
  .sort((a, b) => (a.start > b.start ? 1 : -1))
  .map(c => `${c.name} on ${c.start}`)
console.log(companyStartYear)

// ["Malayan Banking on 1981", "Lelong on 1981", "Perodua on 1986", "CIMB Bank on 1987", "Shopee on 1989", "Lazada on 1992", "Proton on 1999", "Bangkit Technology on 2009", "Komrad Ventures on 2011"]

REDUCE()

Rujukan: reduce

Pada aku function ni adalah function yang paling complicated tetapi “powerful”. Banyak perkara yang boleh dibuat dengan function reduce ni. Antaranya untuk hasil tambah kesemua element pada array. Untuk array ini aku nak terangkan sedikit tentang parameter yang diterima oleh function ini. Asasnya .reduce() diguna begini:

array.reduce(callbackFunction, accumulator)

// contoh

const sumAge = ages.reduce((accumulator, currentValue) => {
  return accumulator + currentValue
}, 0)

console.log(sumAge) // 460

Jika function .reduce() tidak diberikan parameter kedua (accumulator), contoh: [1,2,3,4].reduce( (a , b) => a + n ); , accumulator adalah element pertama dalam array tersebut. disini adalah nombor 1 dan hasil tambah semua element adalah 10. Jadi aliran function ini adalah seperti berikut:

callback accumulator currentValue currentIndex array return value
first call 1 2 1 [1,2,3,4] 3
second call 3 3 2 [1,2,3,4] 6
third call 6 4 3 [1,2,3,4] 10

Jika parameter kedua diberikan, contoh: [1,2,3,4].reduce( (a , b) => a + b ), 5);, accumulator adalah nombor 5 dan hasil tambah semua element adalah 15. Jadi Aliran Function adalah seperti berikut:

callback accumulator currentValue currentIndex array return value
first call 5 1 0 [1,2,3,4] 6
second call 6 2 1 [1,2,3,4] 8
third call 8 3 2 [1,2,3,4] 11
fourth call 11 4 3 [1,2,3,4] 15

CONTOH PENGGUNAAN GABUNGAN FUNCTION

const gabung = ages
  .map(age => age * 2)
  .filter(age => age >= 40)
  .sort((a, b) => a - b)
  .reduce((a, b) => a + b, 0)

console.log(gabung) // 798

Update 15 OCT 2019

Update ni untuk tambah sedikit function yang boleh digunakan untuk array

FIND()

Rujukan: find

function find ini digunakan untuk mencari / mendapatkan element pertama yang wujud di dalam array kita. Contohnya kita nak tahu ada tak bernama lazada. Jika wujud akan return element/obj yang dijumpai. jiki tidak, return undefined.

const lazada = companies.find(company => company.nama === "Lazada") // return object / element yang dijumpai

console.log(lazada) // { name: "Lazada", category: "Retail", start: 1992, end: 2008 }

const lalu = companies.find(company => company.nama === "Lalu") // return undefined

INCLUDES()

Rujukan: includes

function ini hampir sama dengan function find(). Bezanya hanyalah simple array sahaja diterma (bukan array objek). Result nya akan return boolean.

const ageOf5 = age.includes(5)
console.log(ageOf5) // true

const ageOf100 = age.includes(100)
console.log(ageOf100) // false

SOME()

Rujukan: some

function some() ini digunakan untuk mengetahui jika terdapat / wujud element di dalam sesebuah array. Jika ada sekurang-kurangnya 1 akan return true.

const companyStart = companies.some(company => company.start >= 1987)

console.log(companyStart) // true

const companyStartbefore1970 = companies.some(company => company.start <= 1970)

console.log(companyStartbefore1970) // false

EVERY()

Rujukan: every

function ini juga sama macam function some() yang akan juga return bool. Tetapi jika terdapat semua element yang kita mahu di dalam array itu. jika

const semuaCompanyBungkusBermula1990 = companies.every(
  company => company.end >= 1990
)

console.log(semuaCompanyBungkusBermula1990) // false

const semuaCompanyBungkusBermula1989 = companies.every(
  company => company.end >= 1989
)

console.log(semuaCompanyBungkusBermula1989) // true