陣列扁平化

舞動乾坤發表於2018-08-06

轉載自JS陣列專題1️⃣ ➖ 陣列扁平化

一、什麼是陣列扁平化

  1. 扁平化,顧名思義就是減少複雜性裝飾,使其事物本身更簡潔、簡單,突出主題。
  2. 陣列扁平化,對著上面意思套也知道了,就是將一個複雜的巢狀多層的陣列,一層一層的轉化為層級較少或者只有一層的陣列。

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)); 複製程式碼複製程式碼

番外篇將給大家講解 lodashflatten 的實現原始碼,感謝大家閱讀!

相關文章