1. ホーム
  2. apache-spark

[解決済み】mapとflatMapの違いと、それぞれの良い使用例について教えてください。

2022-03-31 19:59:13

質問

mapとflatMapの違いと、それぞれの良い使用例について、どなたか教えてください。

結果を平坦にする」とはどういう意味ですか? また、どのような場合に有効なのでしょうか?

どのように解決するのですか?

以下は、その違いの例です。 spark-shell セッションになります。

まず、いくつかのデータ、つまり2行のテキストです。

val rdd = sc.parallelize(Seq("Roses are red", "Violets are blue"))  // lines

rdd.collect

    res0: Array[String] = Array("Roses are red", "Violets are blue")

今すぐ map は、長さNのRDDを長さNの別のRDDに変換する。

例えば、2行から2行の長さに写像する。

rdd.map(_.length).collect

    res1: Array[Int] = Array(13, 16)

しかし flatMap (大雑把に言うと)長さNのRDDをN個のコレクションのコレクションに変換し、これらを結果の単一のRDDに平坦化します。

rdd.flatMap(_.split(" ")).collect

    res2: Array[String] = Array("Roses", "are", "red", "Violets", "are", "blue")

1行に複数の単語があり、複数の行がありますが、最終的には単語の配列が1つ出力されます

それを説明するために、行のコレクションから単語のコレクションにflatMappingすると、次のようになります。

["aa bb cc", "", "dd"] => [["aa","bb","cc"],[],["dd"]] => ["aa","bb","cc","dd"]

したがって、入力と出力のRDDは、通常、異なるサイズの flatMap .

を使おうとした場合 map と一緒に split 関数を使うと、ネストした構造体(単語の配列のRDDで、型は RDD[Array[String]] というのも、1つの入力に対して正確に1つの結果を得なければならないからです。

rdd.map(_.split(" ")).collect

    res3: Array[Array[String]] = Array(
                                     Array(Roses, are, red), 
                                     Array(Violets, are, blue)
                                 )

最後に、便利な特殊ケースとして、答えを返さないかもしれない関数とのマッピングがあります。 Option . を使用することができます。 flatMap を返す要素をフィルタリングするために None を返すものから値を抽出し Some :

val rdd = sc.parallelize(Seq(1,2,3,4))

def myfn(x: Int): Option[Int] = if (x <= 2) Some(x * 10) else None

rdd.flatMap(myfn).collect

    res3: Array[Int] = Array(10,20)

(ここで、Optionはむしろ1つの要素か0つの要素を持つリストのように振る舞うことに注意してください)