map と flatMap の違いと、それぞれの適切な使用例について説明してもらえますか?
「結果を平坦化する」とはどういう意味ですか? それは何の役に立つのですか?
ベストアンサー1
セッションとしての違いの例を次に示します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 と出力 RDD のサイズは通常異なりますflatMap
。
map
関数で を使用しようとした場合、入力ごとに正確に 1 つの結果を取得する必要があるため、split
ネストされた構造 ( 型の単語の配列の RDD) になります。RDD[Array[String]]
rdd.map(_.split(" ")).collect
res3: Array[Array[String]] = Array(
Array(Roses, are, red),
Array(Violets, are, blue)
)
最後に、役に立つ特別なケースの 1 つは、答えを返さない可能性のある関数を使用して をマッピングすることです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 つの要素を持つリストのように動作することに注意してください)