轉載自JS陣列專題1️⃣ ➖ 陣列扁平化
一、什麼是陣列扁平化
- 扁平化,顧名思義就是減少複雜性裝飾,使其事物本身更簡潔、簡單,突出主題。
- 陣列扁平化,對著上面意思套也知道了,就是將一個複雜的巢狀多層的陣列,一層一層的轉化為層級較少或者只有一層的陣列。
Ps: flatten
可以使陣列扁平化,效果就會如下:
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr)); // [1, 2, 3, 4]
複製程式碼複製程式碼
從中可以看出,使用
flatten
處理後的陣列只有一層,下面我們來試著實現一下。
二、簡單實現
2.1 普通遞迴
- 這是最容易想到的方法,簡單,清晰!
/* ES6 */
const flatten = (arr) => {
let result = [];
arr.forEach((item, i, arr) => {
if (Array.isArray(item)) {
result = result.concat(flatten(item));
} else {
result.push(arr[i])
}
})
return result;
};
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
/* ES5 */
function flatten(arr) {
var result = [];
for (var i = 0, len = arr.length; i < len; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]))
}
else {
result.push(arr[i])
}
}
return result;
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
2.2 toString()
- 該方法是利用
toString
把陣列變成以逗號分隔的字串,然後遍歷陣列把每一項再變回原來的型別。
先來看下 toString
是怎麼把陣列變成字串的
[1, [2, 3, [4]]].toString()
// "1,2,3,4"
複製程式碼複製程式碼
完整的展示
/* ES6 */
const flatten = (arr) => arr.toString().split(',').map((item) => +item);
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
/* ES5 */
function flatten(arr) {
return arr.toString().split(',').map(function(item){
return +item;
});
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
這種方法使用的場景卻非常有限,必須陣列中元素全部都是
Number
。 也可以全部都為String
,具體實現大家自己體會。
2.3 [].concat.apply
+ some
- 利用
arr.some
判斷當陣列中還有陣列的話,迴圈呼叫flatten
扁平函式(利用[].concat.apply
扁平), 用concat
連線,最終返回arr
;
/* ES6 */
const flatten = (arr) => {
while (arr.some(item => Array.isArray(item))){
arr = [].concat.apply([], arr);
}
return arr;
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
/* ES5 /
/*
- 封裝Array.some
- @param {function} callback - 回撥函式
- @param {any} currentThis - 回撥函式中this指向
*/
Array.prototype.some = function (callback, currentThis){
let context = this;
let flag = false;
currentThis = currentThis || this;
for (var i = 0, len = context.length; i < len; i++) {
const res = callback.call(currentThis, context[i], i, context);
if (res) {
flag = true;
} else if (!flag) {
flag = false;
}
}
return flag;
}
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat.apply([], arr);
}
return arr;
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
2.4 reduce
reduce
本身就是一個迭代迴圈器,通常用於累加,所以根據這一特點有以下:
function flatten(arr){
return arr.reduce(function(prev, cur){
return prev.concat(Array.isArray(cur) ? flatten(cur) : cur)
}, [])
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
2.5 ES6 中的 解構運算子 ...
...
每次只能展開最外層的陣列,被[].concat
後,arr
就扁平化一次。
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
複製程式碼
const arr = [1, [2, [3, 4]]];
console.log(flatten(arr));
複製程式碼複製程式碼
番外篇將給大家講解 lodash
中 flatten
的實現原始碼,感謝大家閱讀!