Skip to content

Instantly share code, notes, and snippets.

@kenmori

kenmori/how_to_reduce.md

Last active Jun 7, 2020
Embed
What would you like to do?
【わかりやすい】Array#reduceの使い方。reduceに強くなる記事。how to reduce

【鍛えよう】reduceの使い方。reduceに強くなる記事。how to use reduce

reduceって何?

  • reduceとはArrayが持つメソッド

使い方は?

["a", "b"]

配列に対して

["a", "b"].reduce(f, initValue)

このように使います。

f関数です。 initValue初期値です

配列の中身、この場合

ab に対して

f

で書かれたことを (初期値を渡さない場合)要素数-1だけ実行します

ちょっと実際やってみましょう

const strArray = ["a", "b", "c"] // 配列

const a = strArray.reduce((a, c) => a + c)
a // "abc"

何が起きたのでしょうか

const a = strArray.reduce((p, c) => p + c)

reduceに渡している

(p, c) => p + c

は関数です

これは p + c

をして結果を返しています

const f = (p, c) => p + c
const a = strArray.reduce(f)

先ほどの例題と同じになりました

reduceの第二引数に初期値は渡してません

reduceに渡してたfstrArray

(初期値を渡さない場合)要素数-1だけ実行します

const strArray = ["a", "b", "c"] // "a" "b" "c"が入っているので
const f = (p, c) => p + c // 2(3-1)回これが実行される
const a = strArray.reduce(f) // 初期値は渡していない

1回目

const f = ("a", "b") => "a" + "b"
const a = strArray.reduce(f)

2回目

const f = ("ab", "c") => "ab" + "c"
const a = strArray.reduce(f)
a // "abc"

になります

ここでreduceの構文をみましょう

reducefには

const f = (p, c, i, a) => {}

4つの引数が渡ってきます(先ほどはiとaを使いませんでした)、

それぞれ、

p(前回の値), c(現在の値), i(インデックス), a(配列) // それぞれprevious, current, index, arrayの略です

です。

これらを使って値を返します。(ここら辺は実際に手を動かしてまた後ほど話します)

今はreduceの第一引数に渡した関数から4つの仮引数が渡ってくるんだと覚えておいてください

["a", "b"].reduce(f, initValue)

reduceメソッドの第二引数に渡すinitValueとはなんでしょう。

これは

reduceが最終的に返す型で

最初にfpに渡ってくる型です

initValueを省略することもできます。

["a", "b"].reduce(f)

その場合

aに渡ってくるのは

["a", "b"].reduce(f)

"a"です

initValueを指定する場合と指定しない場合で動きが変わることに注意です。ここが大事です

  • initValueを指定した場合
    • 最初のpにはその値が渡ってきます
  • initValueを指定しない場合
    • 最初のpには配列の最初の要素が渡ってきます

でどんな時使うの?

  • 配列に入っている要素を違うに変更して返したいとき

型ってなぁに

  • 簡単にいうとデータ構造の形

とは

例えば

"a"

string

ですね。

では

1

は?

number

です。

stringnumberでは使えるメソッドも違います。型が違うからです。

型とはわかりやすくいうと

生まれてきた親が違うと思っておいてください

string

const a = "a" // ここで`string`として生まれました。以降aに入っているのは`stringです
const b = 1 // ここでnumberとして生まれました。以降bに入っているのは`numberです

typeof a // "string"

typeof b // "number"

簡単にいうとこれが型です。

では配列はどうでしょう

配列の型は

[]

のように表現します

const c = [] // 配列として生まれた

オブジェクトは?

{}

です。

const d = {} // オブジェクトとして生まれた

ではこちら

["a", "b"]

こちらは型としてどう表現したらいいと思いますか?

配列にstring型が入っています

配列に入っている要素がstring型の場合を型で示す時はこのように表現します

string[]

じゃあこれは?

[1, 2]

配列に入っている要素がnumber

number[]

です。

配列[]に入っているのはnumber型だからです。

ではこれはどうでしょう。

[{id: 1, name: "a"}]

型としてはどういう表現になるでしょう

{id: number, name: string}[]

型としてはこのような表現になります。

idnameのプロパティはそれぞれ1というnumber

name"a"というstringを持った、

オブジェクト型(誤解が生じやすいところです)です。

これが配列の要素になっています。

これはどうでしょう。同じ形のプロパティの型は同じですが違う値です。

[{id: 1, name: "a"}, {id: 2, name: "b"}]

これも型で表現する場合同じです

{id: number, name: string}[]

です。

だんだん型が何かわかってきましたか。じゃあ、

{id: 1, name: "a", friends: ["b", "c", "d"]}

はどうでしょう。

ある構造(ここではidやnameプロパティを持った)をしているオブジェクトにfriendsstringを要素にもつ配列を持っています。

としてはどのような表現になるでしょう

{id: number, name: string, friends: string[]}

ですね。

では本題です

reduceを使いたいとき

  • 配列に入っている要素を違う型に変更して返したいとき

とは...

1 配列の要素全てを連結する

const strArray = ["a", "b", "c"] // 配列

const a = strArray.reduce((a, c) => a + c)
a // "abc" // string[] -> string

// string[]stringとして返ってきました

2 配列の要素全てを加算する

number[]はどうでしょう

const numrrArray = [1, 2, 3] 

const b = numrrArray.reduce((a, c) => a + c)

b // 6 

1,2,3を全て足して6として返りました

つまり

number[]number

3 あるプロパティの値をkey(プロパティ)にしたオブジェクトを返す

[{id: 1, name: "a"}, {id: 2, name: "b"}]

の型は

{id: number, name: string}[]

これを

{1: {id: 1, name: "a"}, 2: {id: 2, name: "b"}}

にするには

const c = [{id: 1, name: "a"}, {id: 2, name: "b"}]
c.reduce((a, c) => {
 return {...a, [c.id]: c}
}, {})

c // {1: {id: 1, name: "a"}, 2: {id: 2, name: "b"}}

一気に難しくなりました

code

const arr = [{eee: "kenji", value: "22"}, {aa: "keiko", value: "30"}]
arr.reduce((a, n, i) => {
 a["key"] = [...a["key"] || [], Object.keys(n)[0]]
 a["value"] = [...a.value || [], n.value]
 return a
}, {})

3

avarage

[10, 30, 2000].reduce((a, n, i, arr) => {
  if(i === arr.length -1){
   const result = a + n
   return result / 2
  }
  return a + n
})

WIP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment