【Swift】reduceメソッドとは?配列操作とreduce(into:)の使い方!
この記事からわかること
- Swiftのreduceメソッドの使い方
- 配列の操作方法
- reduce(into:)との違い
- 辞書型(Dictionary)を操作する
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.0
- Swift:5.9
- macOS:Sonoma 14.1
reduceメソッドの使い方
func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws -> Result
) rethrows -> Result
Swiftのreduce
メソッドはコレクション(配列など)の要素を単一の値にまとめるための関数です。ちなみにreduce
は「減らす」という意味の英単語になります。具体的には配列内の要素の値を全て合計したい場合などに利用できます。
1つ目の引数initialResult
には初期値を渡します。2つ目の引数nextPartialResult
では計算結果と要素を受け取るクロージャーを参照できます。
let numbers = [1, 2, 3, 4, 5]
// 配列の合計を計算する
let sum = numbers.reduce(0) { (result, element) in
print(result) // 0 → 1 → 3 → 6 → 10 と変化していく
return result + element
}
print(sum) // 出力: 15
reduce
を使用しなくてもforEach
などを使用して実装することも可能ですが、reduce
より少し冗長的になってしまいます。
let numbers = [1, 2, 3, 4, 5]
var sum = 0
numbers.forEach { number in
sum += number
}
print(sum) // 出力: 15
省略記法
2つ目の引数で受け取るクロージャーは以下のように省略することが可能です。その場合は$0
で結果を$1
でコレクションの要素を参照することができます。また1行の場合はreturn
も取り除くことができます。
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(0) {
$0 + $1
}
print(sum) // 出力: 15
reduce
メソッドで演算処理を行う場合はさらに省略した記法を使用することが可能です。Swiftでは演算子はクロージャーとして使用でき、2つの引数を内部的に取得して演算を行う関数として動作します。
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(0, +)
print(sum) // 出力: 15
もちろんInt
型だけではなくString
型などでも動作します。
let characters = ["H", "E", "L", "L", "O"]
let word = characters.reduce("", +)
print(word) // 出力: HELLO
reduce(into:)メソッドの使い方
func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()
) rethrows -> Result
reduce
メソッドは引数違いのreduce(into:)
も用意されています。両者の違いはクロージャー内で受け取るResult
型が変更可能かどうかです。
reduce
メソッドのResult
は定数であり、変更することはできません。reduce(into:)
メソッドのResult
はinout
パラメータとして提供され変更が可能になっています。
実際にコードで見てみるとクロージャー内のresult
に対してreduce(into:)
メソッドは+=
が使用できますが、reduce
メソッドは使用できません。これはreduce
メソッドがresult
自体を更新しているわけではなく、引数で受け取った値をクロージャーの返り値として返しているからです。reduce(into:)
メソッドのクロージャーには返り値はなく引数で受け取るresult
自体がミュータブル(変更可能)で最終的な結果になっています。
let numbers = [1, 2, 3, 4, 5]
let sumReduce = numbers.reduce(0) { (result, element) in
// resultはlet定数で変更不可
return result + element
}
let sumReduceInto = numbers.reduce(into: 0) { (result, element) in
// resultはinoutパラメータで変更可能
result += element
}
辞書型(Dictionary)を扱いやすくなっている
クロージャー内でミュータブルになっていることで辞書型(Dictionary)を扱いやすくなっています。例えば配列内で要素をキーとして重複する数を値で保持する辞書を生成してみます。
reduce
メソッドの場合はイミュータブルなので一度ミュータブルな変数を用意して格納してからreturn
する必要があります。
let characters = ["H", "E", "L", "L", "O"]
let occurrencesWithoutInto = characters.reduce([String: Int]()) { (result, element) in
var result = result // 変更可能な変数に代入
result[element, default: 0] += 1
return result
}
print("reduce()", occurrencesWithoutInto)
// reduce() ["L": 2, "E": 1, "H": 1, "O": 1]
let occurrences = characters.reduce(into: [:]) { (result, element) in
result[element, default: 0] += 1
}
print("reduce(into:)", occurrences)
// reduce(into:) ["E": 1, "L": 2, "H": 1, "O": 1]
一方reduce(into:)
メソッドはミュータブルなのでそのまま格納することが可能になっています。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。