27

Functional Programming Principles in Scalaの Collections の講義を聞いていると、次の例を見ました。

scala> val s = "Hello World"

scala> s.flatMap(c => ("." + c)) // prepend each element with a period
res5: String = .H.e.l.l.o. .W.o.r.l.d

では、なぜオーデルスキー氏がここで a を使わなかったのか気になりmapました。しかし、map を試してみると、予想とは異なる結果が得られました。

scala> s.map(c => ("." + c))
res8: scala.collection.immutable.IndexedSeq[String] = Vector(.H, .e, .l, .l, .o, 
                                                          ". ", .W, .o, .r, .l, 

mapつまり、「シーケンス」内の各項目に関数を適用してから、新しい「シーケンス」を返すので、上記の呼び出しは文字列を返すことを期待していました。

ただし、 amapではなくflatmapaを実行できList[String]ます。

scala> val sList = s.toList
sList: List[Char] = List(H, e, l, l, o,  , W, o, r, l, d)

scala> sList.map(c => "." + c)
res9: List[String] = List(.H, .e, .l, .l, .o, ". ", .W, .o, .r, .l, .d)

なぜ文字列IndexedSeq[String]の呼び出しの戻り値の型だったのですか?map

4

5 に答える 5

31

この動作の理由は、「マップ」を文字列に適用するために、Scala が文字列を一連の文字 ( IndexedSeq[String]) として扱うためです。これは、マップ呼び出しの結果として得られるもので、前述のシーケンスの各要素に対して操作が適用されます。Scala は文字列を apply のシーケンスとして扱ったのでmap、それがmap返されます。

flatMapflattenその後、そのシーケンスを呼び出すだけで、文字列に「変換」されます

于 2013-10-06T13:46:27.717 に答える
16

興味深い「Scala flatMap の例のコレクション」もあります。最初の例では、 と の違いを示していflatMapますmap

scala> val fruits = Seq("apple", "banana", "orange")
fruits: Seq[java.lang.String] = List(apple, banana, orange)

scala> fruits.map(_.toUpperCase)
res0: Seq[java.lang.String] = List(APPLE, BANANA, ORANGE)

scala> fruits.flatMap(_.toUpperCase)
res1: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E)

かなり違いますよね?は aを のシーケンスとして扱う
ため、結果の文字列のリストを一連の文字 ( ) にフラット化します。は と の組み合わせであるため、最初にシーケンスで実行され、次に が実行され、表示される結果が得られます。flatMapStringCharSeq[Char]
flatMapmapflattenmapflatten

これは、 map を実行してから自分自身を平坦化することで確認できます。

scala> val mapResult = fruits.map(_.toUpperCase)
mapResult: Seq[String] = List(APPLE, BANANA, ORANGE)

scala> val flattenResult = mapResult.flatten
flattenResult: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E)
于 2016-03-19T22:54:12.653 に答える
7

map 関数c => ("." + c)は char を受け取り、String を返します。リストを取得してリストのリストを返すようなものです。flatMap はそれを平らにします。

String の代わりに char を返す場合、結果を平坦化する必要はありません。たとえば、"abc".map(c => (c + 1).toChar)"bcd" を返します。

于 2013-10-06T13:52:46.327 に答える
1

文字のリストをmap取得し、それを文字列のリストに変換します。それが結果です。Amapはリストの長さを変更しません。文字列のリストには、元の文字列の文字と同じ数の要素があります。

文字のリストを取得してflatMap文字列のリストに変換し、それらの文字列を再び 1 つの文字列にまとめますflatMapリストのリストを作成せずに、リスト内の 1 つの要素を複数の要素に変換する場合に便利です。(これはもちろん、結果のリストが 0 を含む任意の長さを持つことができることも意味しmapます。空のリストから始めない限り、これは不可能です。)

于 2013-10-06T13:53:34.730 に答える