Scala 减法键并保留被拒绝的值

Scala 减法键并保留被拒绝的值,scala,apache-spark,Scala,Apache Spark,我在玩弄spark,我被一些看似愚蠢的事情缠住了 假设我们有两个RDD: rdd1={(1,2)、(3,4)、(3,6)} rdd2={(3,9)} 如果我做的是rdd1.substrackByKey(rdd2),我会得到{(1,2)},它非常好。但是我还想将被拒绝的值{(3,4),(3,6)}保存到另一个RDD,spark中是否有一个预构建的函数或一种优雅的方法来实现这一点 请记住,我是Spark的新手,任何帮助都将不胜感激,谢谢 不幸的是,我认为使用subtractByKey()保存被拒绝的

我在玩弄spark,我被一些看似愚蠢的事情缠住了

假设我们有两个RDD:

rdd1={(1,2)、(3,4)、(3,6)}

rdd2={(3,9)}

如果我做的是
rdd1.substrackByKey(rdd2)
,我会得到
{(1,2)}
,它非常好。但是我还想将被拒绝的值
{(3,4),(3,6)}
保存到另一个RDD,spark中是否有一个预构建的函数或一种优雅的方法来实现这一点


请记住,我是Spark的新手,任何帮助都将不胜感激,谢谢

不幸的是,我认为使用
subtractByKey()
保存被拒绝的值不是一个简单的方法。我认为你得到你想要的结果的一种方法是通过组合和过滤。比如:

val cogrouped = rdd1.cogroup(rdd2, numPartitions)
def flatFunc[A, B](key: A, values: Iterable[B]) : Iterable[(A, B)] = for {value <- values} yield (key, value)
val res1 = cogrouped.filter(_._2._2.isEmpty).flatMap { case (key, values) => flatFunc(key, values._1) }
val res2 = cogrouped.filter(_._2._2.nonEmpty).flatMap { case (key, values) => flatFunc(key, values._1) }
val cogroup=rdd1.cogroup(rdd2,numPartitions)
def flatFunc[A,B](键:A,值:Iterable[B]):Iterable[(A,B)]=对于{value flatFunc(键,值._1)}
val res2=cogroup.filter(u._2._2.非空).flatMap{case(key,values)=>flatFunc(key,values._1)}
你也许可以借用这句话,让最后两行看起来更优雅

当我在您的示例中运行此操作时,我看到:

scala> val rdd1 = sc.parallelize(Array((1, 2), (3, 4), (3, 6)))
scala> val rdd2 = sc.parallelize(Array((3, 9)))
scala> val cogrouped = rdd1.cogroup(rdd2)
scala> def flatFunc[A, B](key: A, values: Iterable[B]) : Iterable[(A, B)] = for {value <- values} yield (key, value)
scala> val res1 = cogrouped.filter(_._2._2.isEmpty).flatMap { case (key, values) => flatFunc(key, values._1) }
scala> val res2 = cogrouped.filter(_._2._2.nonEmpty).flatMap { case (key, values) => flatFunc(key, values._1) }
scala> res1.collect()
...
res7: Array[(Int, Int)] = Array((1,2))
scala> res2.collect()
...
res8: Array[(Int, Int)] = Array((3,4), (3,6))
scala>val rdd1=sc.parallelize(数组((1,2)、(3,4)、(3,6)))
scala>val rdd2=sc.parallelize(数组((3,9)))
scala>val cogroup=rdd1.cogroup(rdd2)
scala>def flatFunc[A,B](键:A,值:Iterable[B]):Iterable[(A,B)]=对于{value val res1=cogroup.filter(u._2._2.isEmpty).flatMap{case(键,值)=>flatFunc(键,值._1)}
scala>val res2=cogrouped.filter(u._2._2.非空).flatMap{case(key,values)=>flatFunc(key,values._1)}
scala>res1.collect()
...
res7:Array[(Int,Int)]=数组((1,2))
scala>res2.collect()
...
res8:Array[(Int,Int)]=数组((3,4)、(3,6))

正如Rohan所建议的,没有(据我所知)标准API调用来执行此操作。您要执行的操作可以表示为
联合交叉点

以下是如何在spark上执行此操作:

val r1 = sc.parallelize(Seq((1,2), (3,4), (3,6)))
val r2 = sc.parallelize(Seq((3,9)))

val intersection = r1.map(_._1).intersection(r2.map(_._1))
val union = r1.map(_._1).union(r2.map(_._1))

val diff = union.subtract(intersection)

diff.collect()
> Array[Int] = Array(1) 
要获取实际对,请执行以下操作:

val d = diff.collect() 
r1.union(r2).filter(x => d.contains(x._1)).collect

我想我认为这更优雅一点:

val r1 = sc.parallelize(Seq((1,2), (3,4), (3,6)))
val r2 = sc.parallelize(Seq((3,9)))

val r3 = r1.leftOuterJoin(r2)
val subtracted = r3.filter(_._2._2.isEmpty).map(x=>(x._1, x._2._1))
val discarded = r3.filter(_._2._2.nonEmpty).map(x=>(x._1, x._2._1))

//subtracted: (1,2)
//discarded: (3,4)(3,6)
我们注意到,
leftOuterJoin
一次性生成丢弃的(=记录,在
r2
中有匹配的键)和剩余的(没有匹配的键)

遗憾的是Spark没有
RDD.partition
(在Scala collection的意义上,根据谓词将集合一分为二),或者我们可以一次计算
减去
丢弃的
,您可以试试

val rdd3 = rdd1.subtractByKey(rdd2)
val rdd4 = rdd1.subtractByKey(rdd3)
但您不需要保留这些值,只需运行另一个减法。

首先使用substractByKey(),然后使用减法

val rdd1 = spark.sparkContext.parallelize(Seq((1,2), (3,4), (3,5)))
val rdd2 = spark.sparkContext.parallelize(Seq((3,10)))

val result = rdd1.subtractByKey(rdd2)
result.foreach(print) // (1,2)

val rejected = rdd1.subtract(result)
rejected.foreach(print) // (3,5)(3,4)

就性能而言,我不确定我是否喜欢它,但只要
diff
不是很大,它就应该工作得足够好。否则
d.contains
闭包将变得相当大。我认为如果
r2
包含重复的键,这不起作用(这就是为什么我使用
cogroup
)。您最终会得到重复的元组。确实如此。希望OP能够澄清重复的元组是否会出现在它们的用例中