-
Notifications
You must be signed in to change notification settings - Fork 0
/
13-2.html
193 lines (178 loc) · 6.87 KB
/
13-2.html
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="./public/favicon.ico" />
<meta http-equiv="cache-control" content="no-cache" />
<title></title>
<link rel="stylesheet" href=" https://necolas.github.io/normalize.css/8.0.1/normalize.css" />
<link rel="stylesheet" href="./hightlight/default.min.css" />
<link rel="stylesheet" href="./css/main.css" />
<link rel="stylesheet" href="./css/copybutton.css" />
<link rel="stylesheet" href="./css/hightlight.css" />
<script src="./hightlight/hightlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BEVZJDBC7Z"></script>
<script src="./js/gtag.js"></script>
</head>
<body>
<header>
<nav>
<h1>
<span id="toggle-menu"></span>
<a href="index.html"></a>
</h1>
</nav>
</header>
<main>
<aside>
<nav></nav>
</aside>
<article>
<h2 id="13-2">13-2 Array.prototype.flatMap()</h2>
<p>flatMap() 方法是一個疊代方法。可以看作是 map 和 depth 為 1 的 flat 的組合。</p>
<pre><code class="language-js">
console.time();
const words = [`hello`, `world`];
const r1 = words.map((item) => item.split(``)).flat();
console.log(r1);
console.timeEnd();
// ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
console.time();
const r2 = words.flatMap((item) => item.split(``));
console.log(r2);
console.timeEnd();
// ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
</code></pre>
<p>
看起來是不是結果都一樣?但是第二種方法的性能會高一些,畢竟第一種要跑兩次方法,中間迴圈多次。如果後面遇到需要先
map 再 flat 一層的情況,我們就可以優先使用 flatMap因為性能較好。
</p>
<p>
flatMap
的使用我們也不能局限到上面的場景,看上面方法的定義,只要是回傳一個陣列就可以。那麽我們就可以實現對結果的新增、刪除、修改
</p>
<pre><code class="language-js">
const words = [`hello`, `world`];
const r3 = words.flatMap((item, index) =>
(index === 0 ? item.split(``).concat(`,`) : item.split(``)));
console.log(r3);// 給單字的間隔加了一個逗號
// ['h', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd']
const number = [1, 2, 3];
const r4 = number.flatMap((item) => [item, item ** item]);
console.log(r4);
// [1, 1, 2, 4, 3, 27]
</code></pre>
<h3>替代方法</h3>
<pre><code class="language-js">
const arr = [1, 2, 3, 4];
arr.flatMap((x) => [x, x * 2]);
// 等同於
const n = arr.length;
const acc = new Array(n * 2);
for (let i = 0; i < n; i++) {
const x = arr[i];
acc[i * 2] = x;
acc[i * 2 + 1] = x * 2;
}
// [1, 2, 2, 4, 3, 6, 4, 8]
</code></pre>
<p>
需要注意的是,在這種特定情況下,flatMap 方法的性能比 for
迴圈要慢——因為需要創建臨時陣列並進行垃圾回收,同時回傳的陣列不需要經常調整大小。但是,在注重靈活性和可讀性的情況下,flatMap
仍可能是正確的解決方案。
</p>
<h3>案例演示</h3>
<h4>比較 map 和 flatMap</h4>
<pre><code class="language-js">
const arr1 = [1, 2, 3, 4];
arr1.map((x) => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap((x) => [x * 2]);
// [2, 4, 6, 8]
// 只有一層被壓平
arr1.flatMap((x) => [[x * 2]]);
// [[2], [4], [6], [8]]
</code></pre>
<h4>flatMap 單字處理</h4>
<p>還可以處理單詞,但須注意 flatMap 輸入輸出 length 不同</p>
<pre><code class="language-js">
const arr1 = ["it's Sunny in", "", "California"];
arr1.map((x) => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]
arr1.flatMap((x) => x.split(" "));
// ["it's","Sunny","in", "", "California"]
</code></pre>
<h4>在 map() 方法過程中新增和刪除元素</h4>
<p>
flatMap 方法可以用作在 map
方法中添加和刪除元素(修改元質數量)的方法。換句話說,它允許你將一些項處理為另一些項(通過單獨處理每個輸入項),而不總是一對一的。在這個意義上,它的作用類似於
filter
的相反操作。如果要保留該項,則回傳一個包含該項的單元素陣列,如果要添加元素,則回傳一個包含多個元素的陣列,如果要刪除該項,則回傳一個空陣列。
</p>
<pre><code class="language-js">
// 假設我們想要刪除所有負數,並將奇數拆分成偶數和 1
const a = [5, 4, -3, 20, 17, -33, -4, 18];
// |\ \ x | | \ x x |
// [4,1, 4, 20, 16, 1, 18]
const result = a.flatMap((n) => {
if (n < 0) {
return [];
}
return n % 2 === 0 ? [n] : [n - 1, 1];
});
console.log(result); // [4, 1, 4, 20, 16, 1, 18]
</code></pre>
<h4>在稀疏陣列上使用 flatMap()</h4>
<p>
callbackFn 不會被源陣列中的空槽調用,因為 map() 不會調用,而 flat()
將忽略回傳陣列中的空槽。
</p>
<pre><code class="language-js">
console.log([1, 2, , 4, 5].flatMap((x) => [x, x * 2])); // [1, 2, 2, 4, 4, 8, 5, 10]
console.log([1, 2, 3, 4].flatMap((x) => [, x * 2])); // [2, 4, 6, 8]
</code></pre>
<h4>在非陣列物件上調用 flatMap()</h4>
<p>
flatMap() 方法讀取 this 的 length
屬性,然後訪問每個整數索引。如果回呼函數的回傳值不是陣列,則始終直接將其附加到結果陣列的末尾。
</p>
<pre><code class="language-js">
const arrayLike = {
length: 3,
0: 1,
1: 2,
2: 3,
};
console.log(Array.prototype.flatMap.call(arrayLike, (x) => [x, x * 2]));
// [1, 2, 2, 4, 3, 6]
// 回呼函式回傳的類陣列物件不會被壓平
console.log(
Array.prototype.flatMap.call(arrayLike, (x) => ({
length: 1,
0: x,
})),
);
// [ { '0': 1, length: 1 }, { '0': 2, length: 1 }, { '0': 3, length: 1 } ]
</code></pre>
<p>資料來源:</p>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap"
>
https://developer.mozilla.org/.../flatMap
</a>
</p>
<p>
<a href="https://juejin.cn/post/7023895016384757796">
https://juejin.cn/post/7023895016384757796
</a>
</p>
</article>
</main>
</body>
<script type="module" src="./js/main.js"></script>
</html>