reduceって何?
reduce
とはArray
が持つメソッド
使い方は?
["a", "b"]
配列に対して
["a", "b"].reduce(f, initValue)
このように使います。
f
は関数
です。
initValue
は初期値
です
配列の中身、この場合
a
と b
に対して
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
に渡してたf
はstrArray
の
(初期値を渡さない場合)要素数-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の構文をみましょう
reduce
のf
には
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が最終的に返す型で
最初にf
のp
に渡ってくる型です
initValueを省略することもできます。
["a", "b"].reduce(f)
その場合
aに渡ってくるのは
["a", "b"].reduce(f)
"a"
です
initValue
を指定する場合と指定しない場合で動きが変わることに注意です。ここが大事です
- initValueを指定した場合
- 最初の
p
にはその値が渡ってきます
- 最初の
initValue
を指定しない場合- 最初の
p
には配列の最初の要素が渡ってきます
- 最初の
でどんな時使うの?
- 配列に入っている要素を違う型に変更して返したいとき
型ってなぁに
- 簡単にいうとデータ構造の形
型
とは
例えば
"a"
はstring
ですね。
では
1
は?
number
です。
string
とnumber
では使えるメソッドも違います。型が違うからです。
型とはわかりやすくいうと
生まれてきた親が違う
と思っておいてください
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}[]
型としてはこのような表現になります。
id
とname
のプロパティはそれぞれ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
プロパティを持った)をしているオブジェクトにfriends
はstring
を要素にもつ配列を持っています。
型
としてはどのような表現になるでしょう
{id: number, name: string, friends: string[]}
ですね。
では本題です
reduceを使いたいとき
- 配列に入っている要素を違う型に変更して返したいとき
とは...
const strArray = ["a", "b", "c"] // 配列
const a = strArray.reduce((a, c) => a + c)
a // "abc" // string[] -> string
// string[]
が string
として返ってきました
number[]
はどうでしょう
const numrrArray = [1, 2, 3]
const b = numrrArray.reduce((a, c) => a + c)
b // 6
1
,2
,3
を全て足して6
として返りました
つまり
number[]
がnumber
[{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"}}
一気に難しくなりました
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
}, {})
[10, 30, 2000].reduce((a, n, i, arr) => {
if(i === arr.length -1){
const result = a + n
return result / 2
}
return a + n
})