我有数据类型:
counted: org.apache.spark.rdd.RDD[(String, Seq[(String, Int)])] = MapPartitionsRDD[24] at groupByKey at <console>:28
我正在尝试将以下内容应用于此类型:
def func = 2
counted.flatMap { x => counted.map { y => ((x._1+","+y._1),func) } }
因此,将每个序列相互比较并应用函数。为简单起见,函数只返回2.当我尝试上面的函数时,我收到这个错误:
scala> counted.flatMap { x => counted.map { y => ((x._1+","+y._1),func) } }
<console>:33: error: type mismatch;
found : org.apache.spark.rdd.RDD[(String, Int)]
required: TraversableOnce[?]
counted.flatMap { x => counted.map { y => ((x._1+","+y._1),func) } }
如何使用Spark?
应用此功能我试过了
val dataArray = counted.collect
dataArray.flatMap { x => dataArray.map { y => ((x._1+","+y._1),func) } }
将集合转换为Array类型并应用相同的函数。但是当我尝试这种方法时,我的内存耗尽了。我认为使用RDD比使用数组效率更高?我可以分配的最大内存量是7g,是否有一种火花机制我可以使用硬盘内存来增加可用的RAM内存?
我正在运行此功能的集合包含20'000个条目,因此20'000 ^ 2比较(400'000'000)但是在Spark方面这个很小?
答案 0 :(得分:2)
简短回答:
counted.cartesian(counted).map {
case ((x, _), (y, _)) => (x + "," + y, func)
}
请使用模式匹配来提取嵌套元组的元组元素,以避免不可读的链式下划线表示法。使用_
作为第二个元素会向读者显示这些值被忽略。
如果func
没有使用第二个元素,那么更具可读性(也许更有效)的是:
val projected = counted.map(_._1)
projected.cartesian(projected).map(x => (x._1 + "," + x._2, func))
请注意,如果你的lambda适合单个语义行,那么你不需要大括号,这在Scala中是一个非常常见的错误。
我想知道为什么你希望拥有这种笛卡尔产品,通常有办法避免这样做,这些产品具有更高的可扩展性。请说明您将如何处理这款笛卡尔产品,我将尝试找到一种可扩展的方式来做您想做的事。
最后一点; 请在运营商之间添加空格
答案 1 :(得分:1)
@RexKerr指出我在评论部分有点不正确,所以我删除了我的评论。但是在这样做的时候,我又有机会再次阅读这篇文章,并提出了可能对你有用的想法。
由于您尝试实现的实际上是对笛卡尔积的某些操作,您可能只想尝试调用RDD#cartesian
。这是一个愚蠢的例子,但如果你能提供一些真实的代码,也许我也可以在这种情况下做这样的事情:
// get collection with the type corresponding to the type in question:
val v1 = sc.parallelize(List("q"-> (".", 0), "s"->(".", 1), "f" -> (".", 2))).groupByKey
// try doing something
v1.cartesian(v1).map{x => (x._1._1+","+x._1._1, 2)}.foreach(println)