將 map、filter、reduce 的運作結果用 emoji 表示

忘記在爬什麼文的時候,發現一張來自 五倍紅寶石的 Elixir installation party 的簡報照片,上面用了各種 Emoji、以及食材料理前與料理後的譬喻,來說明陣列方法:map、filter、reduce 該怎麼理解。

1
2
3
4
# 簡報上的程式碼
map(['🐮', '🥔', '🐔', '🌽'], cook) # => ["🍔", "🍟", "🍗", "🍿"]
filter(['🍔', '🍟', '🍗', '🍿'], isVegetarian) # => ["🥔", "🌽"]
reduce(['🍔', '🍟', '🍗', '🍿'], eat) # => "💩"

因為覺得滿有趣的,所以決定改寫成 JavaScript 的版本玩看看 XD

食材間的對應關係與資料設定

在照片中,有用到了九種 Emoji。其中四種是料理前的食材:🐮🥔🐔🌽,四種是料理後的…料理:🍔🍟🍗🍿,剩下一種是消化後的大便 💩。

此外,由於後續會需要判別哪些食物是給素食者吃的,所以也需要對食物貼上是否是素食的標籤。像🍟🍿這兩個食物就需要貼上。以下是我部份的食物資料設定:

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
27
28
29
const foodData = {
'🐮': {
name: 'cow',
before: '🐮',
after: '🍔',
vegetable: false
},
'🥔': {
name: 'potato',
before: '🥔',
after: '🍟',
vegetable: true
},
...
,
'🍔': {
name: 'hamburger',
before: '🍔',
after: '',
vegetable: false
},
'🍟': {
name: 'fries',
before: '🍟',
after: '',
vegetable: true
},
...
}

用 Emoji 來當物件的 key 還滿新鮮的 XD

map

在 EcmaScript 5.1 中,Array.prototype 已經有內建 map、filter、reduce 方法了,所以可以直接拿來用。

而使用 map 的目的則是:經過烹煮後,['🐮', '🥔', '🐔', '🌽'] 這四個食材,就會變成 ["🍔", "🍟", "🍗", "🍿"] 惹。yummy

1
2
3
4
5
6
// map
function cook(item, index, array) {
return foodData[item].after
}

['🐮', '🥔', '🐔', '🌽'].map(cook) // => ["🍔", "🍟", "🍗", "🍿"]

filter

使用 filter,就可以將素食的料理挑出來,其他不是素食的料理就當作沒看見。

1
2
3
4
5
6
// filter
function isVegetarian(item, index, array) {
return foodData[item].vegetable
}

['🍔', '🍟', '🍗', '🍿'].filter(isVegetarian) // => ["🥔", "🌽"]

reduce

經過 reduce 的消化作用後,吃下去的料理就會變成 💩 惹

1
2
3
4
5
6
// reduce
function eat(item, index, array) {
return '💩'
}

['🍔', '🍟', '🍗', '🍿'].reduce(eat) // => "💩"

小結

以下是完整程式碼

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
* 用 Emoji 表示 map、filter、reduce 的概念
*/
var foodData = {
'🐮': {
name: 'cow',
before: '🐮',
after: '🍔',
vegetable: false
},
'🥔': {
name: 'potato',
before: '🥔',
after: '🍟',
vegetable: true
},
'🐔': {
name: 'chicken',
before: '🐔',
after: '🍗',
vegetable: false
},
'🌽': {
name: 'corn',
before: '🌽',
after: '🍿',
vegetable: true
},
'🍔': {
name: 'hamburger',
before: '🍔',
after: '',
vegetable: false
},
'🍟': {
name: 'fries',
before: '🍟',
after: '',
vegetable: true
},
'🍗': {
name: 'drumstick',
before: '🍗',
after: '',
vegetable: false
},
'🍿': {
name: 'popcorn',
before: '🍿',
after: '',
vegetable: true
},
}
 

function cook(item, index, array) {
return foodData[item].after
}
['🐮', '🥔', '🐔', '🌽'].map(cook) // => ["🍔", "🍟", "🍗", "🍿"]

function isVegetarian(item, index, array) {
return foodData[item].vegetable
}
['🍔', '🍟', '🍗', '🍿'].filter(isVegetarian) // => ["🥔", "🌽"]

function eat(item, index, array) {
return '💩'
}
['🍔', '🍟', '🍗', '🍿'].reduce(eat) // => "💩"