LoginSignup
2
0

More than 3 years have passed since last update.

[JavaScript] reduce で配列を合成する際のベストプラクティス考

Last updated at Posted at 2020-08-01

概要

  • JavaScript で reduce により配列を合成する際、どの方法が速いのかを調べてみました。

比較対象

  • 以下の実装を高階関数で書き替えるのを想定してます。
  • 高階関数使用時の比較なので、「for 文の方が速いかどうか」は、今回の調査対象外です。
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']

const results = []
for (const i in a) {
  results.push(...info[a[i]])
}

console.log(results)
// [11, 13, 15, 22, 24, 26, 33, 35, 37]

候補

  • [].push()
;['a', 'b', 'c']
  .map(key => info[key])
  .reduce(
    (stack, it) => {
      stack.push(...it)
      return stack
    },
    []
  )
  • [].concat()
;['a', 'b', 'c']
  .map(key => info[key])
  .reduce((stack, it) => stack.concat(it))
  • [].push() + ,
;['a', 'b', 'c']
  .map(key => info[key])
  .reduce(
    (stack, it) => (stack.push(...it), stack),
    []
  )
  • flatMap
;['a', 'b', 'c'].flatMap(key => info[key])

計測

  • 100万回ほど回してみました。
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']
const m = 100 * 10000
console.time('push()')
for (let i = 0; i < m; ++i) {
  a.map(key => info[key])
   .reduce(
     (stack, it) => {
       stack.push(...it)
       return stack
     },
     []
   )
}
console.timeEnd('push()')
// push(): 1256.3330078125ms
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']
const m = 100 * 10000
console.time('concat()')
for (let i = 0; i < m; ++i) {
  a.map(key => info[key])
   .reduce((stack, it) => stack.concat(it))
}
console.timeEnd('concat()')
// concat(): 547.2890625ms
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']
const m = 100 * 10000
console.time('push() + ,')
for (let i = 0; i < m; ++i) {
  a.map(key => info[key])
   .reduce(
     (stack, it) => (stack.push(...it), stack),
     []
   )
}
console.timeEnd('push() + ,')
// push() + ,: 1409.1591796875ms
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']
const m = 100 * 10000
console.time('flatMap')
for (let i = 0; i < m; ++i) {
  a.flatMap(key => info[key])
}
console.timeEnd('flatMap')
// flatMap: 3049.98095703125ms

結果

  • 構文としては flatMap が一番スマートですが、速度では concat() による reduce が優る模様。
優勝
const info = {
  a: [11, 13, 15],
  b: [22, 24, 26],
  c: [33, 35, 37],
}
const a = ['a', 'b', 'c']

a.map(key => info[key])
 .reduce((stack, it) => stack.concat(it))
  • さらに、コンマ演算子は reduce に渡す関数の構成で速度を僅かながら上げてくれる事もわかりました。
    計測ミスでした。

  • 高階関数を使うのは必須として、さらに速い実装があれば教えて下さい!
    (・ω・)< for が速いのは存じております故

2
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0