【Swift】reduceメソッドとは?配列操作とreduce(into:)の使い方!

【Swift】reduceメソッドとは?配列操作とreduce(into:)の使い方!

この記事からわかること

  • Swiftreduceメソッド使い方
  • 配列操作方法
  • reduce(into:)との違い
  • 辞書型(Dictionary)を操作する

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

reduceメソッドの使い方

定義:公式リファレンス: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:)メソッドの使い方

定義:公式リファレンス:reduce(into:)メソッド

func reduce<Result>(
    into initialResult: Result,
    _ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()
) rethrows -> Result

reduceメソッドは引数違いのreduce(into:)も用意されています。両者の違いはクロージャー内で受け取るResult型が変更可能かどうかです。

reduceメソッドのResultは定数であり、変更することはできません。reduce(into:)メソッドのResultinoutパラメータとして提供され変更が可能になっています。

実際にコードで見てみるとクロージャー内の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:)メソッドはミュータブルなのでそのまま格納することが可能になっています。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index