一道關於 ARRAY 深度展開的面試題

今天面試的時候,考官出了這麼一個題,寫一個函數,輸入a = [1,[2,3,[4,5,6]]],輸出a = [1,2,3,4,5,6]。當時我腦子有點短路,作了很久,給出了個不太符合要求的答案以下git

var a = [1,[2,3,[4,5,6]]]
var arr = []
function merge(a) {
  for(var i = 0; i < a.length; i++){
    if(Array.isArray(a[i])){
      merge(a[i])
    } else {
      arr.push(a[i])
    }
  }
  return arr
}

回家後稍微完善了下,符合了考官輸入輸出的要求了(不過也晚了)github

function flatten(a) {
  if (!Array.isArray(a)) return

  var arr = []

  return (function merge(a) {
    for(var i = 0, l = a.length; i < l; i++){
      if(Array.isArray(a[i])){
        merge(a[i])
      } else {
        arr.push(a[i])
      }
    }
    return arr
  })(a)
}

而後跟朋友聊天問問有啥簡單的方法,朋友給了一個挺符合這個題的簡單方法相似以下面試

const flatten = (arr) => arr.toString().split(',').map(v => Number(v))

不過這個答案只適用於這道題,若是不是全數字的就不行了。因而在GitHub上搜索array flatten,看了看排名前三的源碼,發現有好多不一樣的寫法,好比npm

function flatten() {
  var args = Array.from(arguments)
  do {
    args = [].concat.apply([], args)
  } while (args.some(Array.isArray))
  return args
}

也有這麼寫的app

function flatten (array) {
  var result = Array.prototype.concat.apply([], array)
  if (result.length === array.length) {
    return result
  }
  return flatten(result)
}

寫法各不相同,還有好多看似相似,但細節上不同的,因此關鍵就看性能了,好在arr-flattenarray-flatten中就都有benchmark,進行了各類比較函數

arr-flatten這個項目中,在各類不一樣的、能夠在 npm 上搜到的array flatten實現方法之間進行了比較,最後的結論是array-flatten執行的效率最高性能

array-flatten項目裏的benchmark主要是本身源碼中細節不一樣的寫法之間的差別,最後得出的最佳實踐以下測試

function flatten (array) {
  if (!Array.isArray(array)) {
    throw new TypeError('Expected value to be an array')
  }
  return flattenFrom(array)
}

function flattenFrom (array) {
  return flattenDown(array, [])
}

function flattenDown (array, result) {
  for (var i = 0; i < array.length; i++) {
    var value = array[i]

    if (Array.isArray(value)) {
      flattenDown(value, result)
    } else {
      result.push(value)
    }
  }

  return result
}

這套代碼思路與我給出的答案是同樣的,但因爲細節上的不一樣,致使用benchmark測試,執行效率比我寫的那個快了約20%spa

相關文章
相關標籤/搜索