[英]Scala Spark filter inside map
我想在映射時有效地過濾RDD。 那可能嗎?
這是我想要做的偽代碼:
for element in rdd:
val opt = f(element)
if (opt.nonEmpty) add_pair(opt.get, element)
這是在Scala Spark中實現偽代碼的一種hacky方法:
rdd.map(element => (
f(element).getOrElse(99),
element
)).filter(tuple => tuple._1 != 99)
我無法找到干凈的語法來做到這一點,所以我首先映射所有元素,然后過濾掉我不想要的。 請注意,可能昂貴的調用f(element)
僅計算一次。 如果我在映射之前過濾元素(看起來會更干凈),那么我最終會調用f
兩次,效率很低。
請不要將此標記為重復。 雖然有類似的問題,但實際上沒有人回答這個問題。 例如, 這個潛在的副本將調用f
兩次,這是低效的,因此不回答這個問題。
你可以使用flatMap
:
//let's say your f returns Some(x*2) for even number and None for odd
def f(n: Int): Option[Int] = if (n % 2) Some(n*2) else None
val rdd = sc.parallelize(List(1,2,3,4))
rdd.flatMap(f) // 4,8
// rdd.flatMap(f) or rdd.flatMap(f(_)) or rdd.flatMap(e => f(e))
如果你需要進一步傳遞元組並過濾,那么只需使用嵌套map
:
rdd.flatMap(e => f(e).map((_,e))) //(4,2),(8,4)
您可以使用mapPartitions
進行過濾以及昂貴的計算。
rdd.mapPartitions( elements =>
elements
.map(element => (f(element),element))
.filter(tuple => tuple._1.isDefined)
)
請注意,在此代碼中, filter
是本機scala集合方法,而不是Spark RDD過濾器。
或者,您也可以flatMap
映射函數的結果
rdd.flatMap(element => f(element).map(result => (result,element)))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.