點燈坊

失くすものさえない今が強くなるチャンスよ

使用 scan() 將 reduce() 過程保留下來

Sam Xiao's Avatar 2019-11-15

reduce() 只能回傳最後運算結果,若連運算的累積過程也要顯示,則要使用 scan()

Version

macOS Catalina 10.15.1
VS Code 1.40.0
Quokka 1.0.259
Ramda 0.26.1

Imperative

let data = [1, 2, 3]

let scan = fn => a => arr => {
  let result = [a];

  for(let x of arr) {
    a = fn(a, x)
    result.push(a)
  }
    
  return result
}

scan((a, x) => a + x)(0)(data); // ?

我們希望將 data reduce 時,還能將過程累計值 a 也保留下來。

Imperative 會使用 for loop 將 x 透過 fn() 運算,並將累計值 a push 進 result array 回傳。

scan000

Array.prototype.reduce()

let data = [1, 2, 3]

let scan = fn => a => arr => {
  let result = [a];
  
  arr.reduce((a, x) => {
    let a_ = fn(a, x)
    result.push(a_)
    return a_
  }, a)

  return result
}
  
scan((a, x) => a + x)(0)(data); // ?

結果為單一 array,因此也可使用 reduce() 完成。

scan000

Ramda

import { scan } from 'ramda'

let data = [1, 2, 3]

scan((a, x) => a + x)(0)(data) // ?

Ramda 已經提供 scan(),可直接使用。

scan()
((a, x) → a) → a → [x] → [a]
將 reduce 過程的累計值全部顯示出來

((a, x) -> a):reducer,其中 a 為 accumulator,x 為 array 的 element

a:accumulator 的初始值

[x]:data 為 array

[a]:回傳以 accumulator 構成的 array

scan002

Conclusion

  • 若要將 reduce() 過程也顯示出來,別忘了 scan()

Reference

MDN, Array.prototype.reduce()
Ramda, scan()