1. 序章
次のチュートリアルでは、ScalaのfoldLeftとreduceLeftの違いを見ていきます。
foldLeftとreduceLeftはどちらも、コレクションの最初の値からコレクションをトラバースする関数です。 関数は各要素に適用され、アキュムレータ値は関数の次の実行ごとに渡されます。 foldLeftおよびreduceLeftは、再帰関数と同じように動作します。
2. メソッドシグネチャ
foldLeftとreduceRightのメソッドシグネチャを見て、それらがどのように動作するかを学びましょう。
2.1. foldLeft署名
foldLeft は、初期シード値で指定された任意の型を返すことができる関数を各要素に適用するコレクションをトラバースします。
foldLeftの署名は次のとおりです。
def foldLeft[B](z: B)(op: (B, A) ⇒ B): B
foldLeft シグニチャから、メソッドが戻り型と同じ型の初期値を期待していることがわかります。 初期値zは、関数のアキュムレータの開始点になります。 A は、トラバースしているコレクション内の要素のタイプであり、戻りタイプBに関連するタイプ制約はありません。
2.2. reduceLeft署名
reduceLeft は、各要素を結合して単一の結果を返すために各要素に関数を適用することにより、コレクションを減らすために使用されます。
reduceLeft署名を見てみましょう。
def reduceLeft[B >: A](op: (B, A) ⇒ B): B
一見すると、 foldLeft、と非常によく似ていますが、次の2つの違いがあります。
- reduceLeftには初期値はありません。 これは、アキュムレータの初期値が、コレクション内で削減したい最初の値になることを意味します
- 「削減」とは、コレクションを削減または縮小することを期待していることを意味します。 AとB([B>:A] )に適用される境界を見ると、削減することが目的であることがわかります。 reduceLeft、では、AとBの間に下位の型境界関係があります。 これは、BがAのサブタイプでなければならないことを意味します
3. 実例
foldLeftとreduceLeftの実際の例をいくつか見て、それらの違いを説明します。
3.1. foldLeftの例
foldLeft の強力な点の1つは、コレクションを変換する際の柔軟性です。 入力タイプと結果タイプにタイプの境界がないため、データを新しいコレクションに変換できます。
これを説明するために、多くの人がいるシステムの例を見てみましょう。
私たちのシステムの人は名前と年齢を持っています:
case class Person(name: String, age: Int)
システム内の人の表現がIDと人のマップであるとしましょう。
val users: Map[Int, Person] =
Map(1 -> Person("Tom", 10), 2 -> Person("Gillian", 13), 3 -> Person("Sarah", 17), 4 -> Person("David", 20))
次に、ユーザーのリストを作成しますが、ユーザーのIDは気にしません。 変革したい Map[Int, Person]
に List[Person]
.
foldLeftは次の場合に使用できます。
val peopleList: List[Person] = people.foldLeft(List.empty[Person])((people, current) => {
people :+ current._2
}
assert(peopleList == List(Person("Tom", 10), Person("Gillian", 13), Person("Sarah", 17), Person("David", 20)))
3.2. reduceLeftの例
ユーザーのリストができたので、最年少のユーザーなど、いくつかの有用な情報を抽出したいと思います。 ユーザーのリストを、年齢が最も低い1人のユーザーに減らします。
val youngestPerson: Person = people.reduceLeft((youngestPerson, currentPerson) => {
if (youngestPerson.age > currentPerson.age) {
currentPerson
else {
youngestPerson
})
assert(youngestPerson == Person("Tom", 10))
上記の例では、 List[Person]を最も若い年齢のPersonに減らしました。
4. 結論
このチュートリアルでは、ScalaのfoldLeftとreduceLeftの違いを確認しました。 いつものように、コードはGitHubでオーバーです。