LoginSignup
30
18

More than 3 years have passed since last update.

Array.prototype.reduce()を使いこなしたい

Posted at

reduce()とは

Array.prototype.reduce()

配列からひとつの値を求めるときに使われる。
いろんなこと出来そう、便利そう、面白そう、、、と思ったので、理解を深めるためにメモに残す。

構文

  1. accumulator(前回の値)
  2. currentValue(現在の値)
  3. currentIndex(現在currentとして処理されている要素のindex)
  4. array(現在操作されている配列)

initialValueは第2引数で初期値がはいる。

const result = array.reduce((accumulator, currentValue, currentIndex, array) => {
  return accumulator
}, initialValue)

arrayの数字を足し上げて、合計値を得る。
初期値(initialValue)は0とする。

const array = [0, 1, 2, 3]
const initialValue = 0

const result = array.reduce(
  (accumulator, currentValue, currentIndex, array) => {
    console.log(
      "accumulator:",
      accumulator,
      "currentValue:",
      currentValue,
      "currentIndex:",
      currentIndex,
      "array:",
      array
    )
    return accumulator + currentValue
  },
  initialValue
)

console.log("result:", result) //6

スクリーンショット 2020-07-11 19.53.35.png

reduce() の返値は、最後の返値である (6) となった。

これをforで書くと。。。
const array = [0, 1, 2, 3]
let value = 0

for (let i = 0; i < array.length; i++) {
  value += array[i]
}

console.log(value) //6
これをforEach()で書くと。。。
const array = [0, 1, 2, 3]
const forEachResult = array => {
  let sum = 0
  array.forEach(number => {
    return (sum += number)
  })
  return sum
}

console.log("forEachResult:", forEachResult(array)) //6

forやforEach()は、「配列の要素を1つずつ処理する」というのが本来の目的であり、reduce() は「単一の値を返す」のが目的なので、reduce()を使うほうが、今回の目的「arrayの数字を足し上げて、合計値を得る」手段としては、適していると言える。

理解を深めるために色々なサンプルコードを書いてみる

sample01: オブジェクトの配列の値の合計値を出す

const initialValue = 0
const array = [{ x: 0 }, { x: 1 }, { x: 2 }, { x: 3 }]

const sample01 = array.reduce((accumulator, currentValue) => {
  return accumulator + currentValue.x
}, initialValue)

console.log(sample01) //6

sample02: 配列から要素を抜き出して、好きな形のオブジェクトにする

const initialValue = {}
const array = [
  { name: "keko", age: 25 },
  { name: "taro", age: 19 },
  { name: "mai", age: 17 }
]

const sample02 = array.reduce((accumulator, currentValue) => {
  accumulator[currentValue.name] = currentValue.age
  return accumulator
}, initialValue)

console.log(sample02) //{keko: 25, taro: 19, mai: 17}

sample03: 配列をindex付きのオブジェクトにする

const initialValue = {}
const array = [
  { name: "keko", age: 25 },
  { name: "taro", age: 19 },
  { name: "mai", age: 17 }
]

const sample03 = array.reduce((accumulator, currentValue, index) => {
  accumulator[index + 1] = currentValue
  return accumulator
}, initialValue)

console.log(sample03)
// {
//   1: {name: "keko", age: 25}
//   2: {name: "taro", age: 19}
//   3: {name: "mai", age: 17}
// }

sample04: 配列を欲しい要素だけにしてオブジェクトにする

const initialValue = []
const array = [
  { name: "keko", age: 25, pref: "Ehime" },
  { name: "taro", age: 19, pref: "Ehime" },
  { name: "mai", age: 17, pref: "Osaka" }
]

const sample04 = {
  ...array.reduce((accumulator, currentValue) => {
    const { name, age } = currentValue
    accumulator.push({ name, age })
    return accumulator
  }, initialValue)
}

console.log(sample04)
// {
//   { name: "keko", age: 25 },
//   { name: "taro", age: 19 },
//   { name: "mai", age: 17 }
// }

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

const initialValue = {};
const array = [
  { name: "keko", age: 25, pref: "Ehime" },
  { name: "taro", age: 19, pref: "Ehime" },
  { name: "mai", age: 17, pref: "Osaka" }
];

const sample05 = array.reduce((accumulator, currentValue) => {
  let key = currentValue.pref;
  if (!accumulator[key]) {
    accumulator[key] = [];
  }
  const { name, age } = currentValue;
  accumulator[key].push({ name, age });
  return accumulator;
}, initialValue);

console.log(sample05);

// {
//   Ehime: [
//     {name: "keko", age: 25 },
//     {name: "taro", age: 19 }],
//   Osaka: [
//     {name: "mai", age: 17 }]
// }

sample06_1: 二次元配列を一次元配列にする(concat編)


const initialValue = []
const array = [[0, 1], [2, 3], [4, 5]]

const sample06_1 = array.reduce((accumulator, currentValue) => {
  return accumulator.concat(currentValue)
}, initialValue)

console.log(sample06_1) // [0, 1, 2, 3, 4, 5]

sample06_2: 二次元配列を一次元配列にする(spred演算子編)

const initialValue = []
const array = [[0, 1], [2, 3], [4, 5]]

const sample06_2 = array.reduce((accumulator, currentValue) => {
  return [...accumulator, ...currentValue]
}, initialValue)

console.log(sample06_2) // [0, 1, 2, 3, 4, 5]

sample07_01: 配列内の重複している値を除外する(someで除外編)

const initialValue = []
const array = [1, 2, 2, 3, 1, "a", "b", "b"]

const sample07_01 = array.reduce((accumulator, currentValue) => {
  if (!accumulator.some(item => item === currentValue)) {
    accumulator.push(currentValue)
  }
  return accumulator
}, initialValue)

console.log(sample07_01)

sample07_02: 配列内の重複している値を除外する(indexOfで除外編)

const initialValue = []
const array = [1, 2, 2, 3, 1, "a", "b", "b"]

const sample07_02 = array.reduce((accumulator, currentValue) => {
  if (accumulator.indexOf(currentValue) === -1) {
    return accumulator.push(currentValue)
  }
  return accumulator
}, initialValue)

console.log(sample07_02)

sample08: filter() + map() の代わりに使う

map() は入力&出力は要素数は変わらないので、配列の一部要素を除外する時、filter() を適用させる必要があり、filter() と map() でそれぞれループするが、reduce() を使えばループは一度で済む。

const initialValue = []
const array = [
  { id: 1, name: "keko", age: 25 },
  { id: 2, name: "taro", age: 19 },
  { id: 3, name: "mai", age: 17 },
  { id: 4, name: "hiro", age: 30 }
]

//未成年を除外して、idとnameを取得して配列にする
const sample08 = array.reduce((accumulator, currentValue) => {
  if (currentValue.age > 20) {
    const { id, name } = currentValue
    accumulator.push({ id, name })
  }
  return accumulator
}, initialValue)

console.log(sample08)
// [
//   {id: 1, name: "keko"},
//   {id: 4, name: "hiro"}
// ]


//filter().map()の場合
const sample08_test = array
.filter(item => item.age > 20)
.map(item => {
  const { id, name } = item;
  return { id, name }
})

console.log(sample08_test)
// [
//   {id: 1, name: "keko"},
//   {id: 4, name: "hiro"}
// ]

sample09: 多次元配列を一次元配列にする

const array = [0, [1, 2, 3, [4, 5], [6, 7, [8, 9]]]];

const mergeArry = arr => {
  const result = arr.reduce((acc, current) => {
    return acc.concat(current);
  }, []);
  return result;
};

const hasArry = arr => arr.some(item => Array.isArray(item));

const mergeAll = arr => {
  if (!hasArry(arr)) {
    return arr;
  }
  const result = mergeArry(arr);
  return mergeAll(result);
};

const sample09 = mergeAll(array);

console.log(sample09); //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

今後もsample追加していく

参考

30
18
0

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
30
18