JavaScript: for-loop から reduce へ


JavaScript: 「最初はこうだったけど、いろいろあって、こうなった」reduceは状態遷移だの続き。
for-loopとreduceで同じことをやって並べてみました。
比較のためにreduceは分かち書きしてます。
こんなfor-loopを書いていたら、そこは reduce に置きかえられるかも?という例です。
MDNのreduceの例から引用。

sum

//for-loop
const sum = msgs =>{
  let  model = 0
  for(let msg of msgs)  model =  model + msg
  return  model
} 
const items = [0,1,2]
sum(items) // 3
//reduce
const  initModel = 0
const update = ( model, msg) =>  model + msg
const sum = msgs => msgs.reduce(update,  initModel)

const items = [0, 1, 2]
sum(items)  //  3

オブジェクトの配列の値の合計値

//for-loop
const sumX = msgs =>{
  let  model = 0
  for(let msg of msgs)  model =  model + msg.x
  return  model
} 
const items = [{x:1}, {x:2}, {x:3}]
sumX(items) // 6
//reduce
const  initModel = 0
const update = (  model, msg ) =>  model + msg.x
const sumX = msgs => msgs.reduce(update,  initModel)

const items = [{x:1}, {x:2}, {x:3}]
sumX(items) // 6

二次元配列を一次元配列に

//for-loop
const flatten = msgs =>{
  let  model = []
  for( let msg of msgs )  model = [...model,  ...msg]
  return  model
} 
const items = [[0, 1], [2, 3], [4, 5]]
flatten(items) // [ 0, 1, 2, 3, 4, 5 ]
//reduce
const  initModel = []
const update = (  model, msg ) => [...model,  ...msg]
const flatten = msgs => msgs.reduce(update,  initModel)

const items = [[0, 1], [2, 3], [4, 5]]
flatten(items) // [ 0, 1, 2, 3, 4, 5 ]

オブジェクトの値のインスタンスを数える

//for-loop
const countedNames = msgs =>{
  let  model = {}
  for(let msg of msgs) {
    if(e in  model)  model[msg] =  model[msg] + 1
    else  model[msg] = 1
  }
  return  model
} 
const items = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
countedNames(items) // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
//reduce
const  initModel = {}
const update = ( model, msg) =>
  msg in  model? {...model, [msg]: model[msg] + 1}
  : {...model, [msg]:1}
const countedNames = msgs => msgs.reduce(update,  initModel)

const items = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
countedNames(items) // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

プロパティによってオブジェクトをグループ化する

//for-loop
const groupBy = prop => msgs => {
  let  model = {}
  for(let msg of msgs) {
    const key = msg[prop]
    if(  model[key] === undefined  )  model[key] = [msg]
    else  model[key] = [...model[key], msg]
  }
  return  model
} 
const items = [
  { name: 'Alice', age: 21 },
  { name: 'Max', age: 20 },
  { name: 'Jane', age: 20 }
]
groupBy('age')(items)
// { '20': [ { name: 'Max', age: 20 }, { name: 'Jane', age: 20 } ],'21': [ { name: 'Alice', age: 21 } ] }
//reduce
const  initModel = {}
const update = prop => ( model, msg) => {
  const key = msg[prop]
  return  model[key] === undefined ? { ...model, [key]:[msg] } 
    : { ...model, [key]:[...model[key], msg] }
}
const groupBy = prop => msgs =>  
  msgs.reduce( update(prop),  initModel )

const items = [
  { name: 'Alice', age: 21 },
  { name: 'Max', age: 20 },
  { name: 'Jane', age: 20 }
]
groupBy('age')(items)
// { '20': [ { name: 'Max', age: 20 }, { name: 'Jane', age: 20 } ],'21': [ { name: 'Alice', age: 21 } ] }