概要
reduce(into:)が便利だったので、備忘録として記録しておきます。
注意
この記事は新卒エンジニアが執筆しています。
そのため内容に間違いや不備がある場合があります。
もし間違いを発見しましたら、どんどん指摘していただけると幸いです。
reduce関数とは
reduce関数とは、配列やコレクションの要素を結合して単一の値を生成するための高度なメソッドです。
よくInt型の配列の合計値を求める際などに使われます。
func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws -> Result
) rethrows -> Result
let array: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let sum = array.reduce(0) { sum, value in sum + value } // 45
reduce(into:)
reduce関数にはinto
パラメータが付いた別バージョンがあります。
大きな違いは、Resultとして渡される1つ目の引数が変更可能であることです。
func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()
) rethrows -> Result
Resultがinout
として渡されているので、クロージャー内で変更が可能になっています。
そのおかげでResultをreturnする必要がなく、コードを簡潔に書くことができます。
辞書型を扱う上でこれが便利だったので、使用例を紹介します。
ArrayからDictionaryへの変換
普通のreduceを使った場合と、reduce(into:)を使った場合のコードを比べてみましょう。
この例ではArray型から辞書型への変換を行なっています。
let array: [(Int, String)] = [(1, "A"), (2, "B"), (3, "C")]
let dictionary: [Int: String] = array.reduce([:]) { result, tuple in
var copyResult = result
copyResult[tuple.0] = tuple.1
return copyResult
}
print(dictionary) // [1: "A", 2: "B", 3: "C"]
let array: [(Int, String)] = [(1, "A"), (2, "B"), (3, "C")]
let dictionary: [Int: String] = array.reduce(into: [:]) { result, tuple in
result[tuple.0] = tuple.1
}
print(dictionary) // [1: "A", 2: "B", 3: "C"]
result(into:)を使うことで、かなり簡潔に書けていると思います。
偶数の数をカウントする
もう1つ具体例を挙げてみます。
いかはInt型の配列から、偶数の数をカウントするコードです。
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let countOfEvenNumbers = numbers.reduce(0) { result, number in
if number % 2 == 0 { return result + 1 }
else { return result }
}
print(countOfEvenNumbers) // 5
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let countOfEvenNumbers = numbers.reduce(into: 0) { result, number in
if number % 2 == 0 { result += 1 }
}
print(countOfEvenNumbers) // 5
地味な変化ですが、reduce(into:)
を使ったほうが簡潔に書くことができます。
まとめ
普通のreduceを使うときは、reduce(into:)
を使ってシンプルに書けないかを考えてみてください。
また他の型から辞書、配列に変換するときもreduce(into:)
を使うと割と簡単に実装できます。