Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何将RDD[Array[String]]转换为RDD[(Int,HashMap[String,List])?_Scala_List_Apache Spark_Hashmap - Fatal编程技术网

Scala 如何将RDD[Array[String]]转换为RDD[(Int,HashMap[String,List])?

Scala 如何将RDD[Array[String]]转换为RDD[(Int,HashMap[String,List])?,scala,list,apache-spark,hashmap,Scala,List,Apache Spark,Hashmap,我有输入数据: time, id, counter, value 00.2, 1 , c1 , 0.2 00.2, 1 , c2 , 0.3 00.2, 1 , c1 , 0.1 我想为每个id创建一个存储计数器和值的结构。在考虑向量并拒绝它们之后,我得出了以下结论: (id, Hashmap( (counter1, List(Values)), (Counter2, List(Values)) )) (1, HashMap( (c1,List(0.2, 0

我有输入数据:

time, id, counter, value
00.2,  1 , c1     ,  0.2
00.2,  1 , c2     ,  0.3
00.2,  1 , c1     ,  0.1
我想为每个id创建一个存储计数器和值的结构。在考虑向量并拒绝它们之后,我得出了以下结论:

(id, Hashmap( (counter1, List(Values)), (Counter2, List(Values)) ))
(1, HashMap( (c1,List(0.2, 0.1)), (c2,List(0.3)))
问题是我无法在映射转换中转换为Hashmap,另外,我不知道是否能够通过映射中的列表计数器来减少

有人知道吗

我的代码是:

val data = inputRdd
          .map(y => (y(1).toInt, mutable.HashMap(y(2), List(y(3).toDouble)))).reduceByKey(_++_)
  }

在我的头顶上,未经测试:

import collection.mutable.HashMap

inputRdd
  .map{ case Array(t, id, c, v) => (id.toInt, (c, v)) }
  .aggregateByKey(HashMap.empty[String, List[String]])(
    { case (m, (c, v)) => { m(c) ::= v; m } },
    { case (m1, m2) => { for ((k, v) <- m2) m1(k) ::= v ; m1 } }
  )
import collection.mutable.HashMap
输入
.map{case数组(t,id,c,v)=>(id.toInt,(c,v))}
.aggregateByKey(HashMap.empty[String,List[String]])(
{case(m,(c,v))=>{m(c)::=v;m},
{case(m1,m2)=>{for((k,v)这里有一种方法:

val rdd = sc.parallelize(Seq(
  ("00.2", 1, "c1", 0.2),
  ("00.2", 1, "c2", 0.3),
  ("00.2", 1, "c1", 0.1)
))

rdd.
  map{ case (t, i, c, v) => (i, (c, v)) }.
  groupByKey.mapValues(
    _.groupBy(_._1).mapValues(_.map(_._2)).map(identity)
  ).
  collect
// res1: Array[(Int, scala.collection.immutable.Map[String,Iterable[Double]])] = Array(
//   (1,Map(c1 -> List(0.2, 0.1), c2 -> List(0.3)))
// )

请注意,最终的
map(identity)
是本文建议的补救措施。

如果如您所述,将
inpurdd
作为

//inputRdd: org.apache.spark.rdd.RDD[Array[String]] = ParallelCollectionRDD[0] at parallelize at ....
然后,对分组值执行一个简单的
groupBy
foldLeft
,就可以获得最终的预期结果

val resultRdd = inputRdd.groupBy(_(1))
                          .mapValues(x => x
                            .foldLeft(Map.empty[String, List[String]]){(a, b) => {
                              if(a.keySet.contains(b(2))){
                                val c = a ++ Map(b(2) -> (a(b(2)) ++ List(b(3))))
                                c
                              }
                              else{
                                val c = a ++ Map(b(2) -> List(b(3)))
                                c
                              }
                            }}
                          )
//resultRdd: org.apache.spark.rdd.RDD[(String, scala.collection.immutable.Map[String,List[String]])] = MapPartitionsRDD[3] at mapValues at ...
//(1,Map(c1 -> List(0.2, 0.1), c2 -> List(0.3)))
RDD[(String,scala.collection.immutable.Map[String,List[String]]]]]]
更改为
RDD[(Int,HashMap[String,List[String]]]]]]
将只是强制转换,我希望您可以更轻松地执行此操作


我希望答案是有帮助的

为什么RDDAPI不是DataFrame/Dataset?!为什么要考虑替换
a.keySet.contains(b(2))
with
mutable.Map
and?@JacekLaskowski感谢您的回复,如果键存在,getOrElseUpdate将返回我的值,否则值是新操作,但是如果键存在,场景就像添加新列表。我只是不知道您的信息如何有助于改进答案?您为什么考虑repl用
case
加下划线?这会提高可读性,从而提高理解能力吗?@Jacek Laskowski,为了可读性,我通常更喜欢使用case和更有意义的变量,而不是元组访问器(特别是当元组大小大于2和/或转换涉及分组/位置洗牌时)。