概要
- 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 が速いのは存じております故