如何在Scala中获得多个列表的平均值

时间:2016-10-11 01:38:58

标签: scala

假设我们有几个列表:

List(List(1,2,3), List(4,5,6), List(7,8,9))

如何获得所有列表中每个元素的平均值?在这种情况下,我们将有 List((1+4+7)/3, (2+5+8)/3, (3+6+9)/3)在这里。

4 个答案:

答案 0 :(得分:3)

假设你想要第一个元素的平均值,然后是所有第二个元素的平均值,等等:

List( List(1,2,3), List(4,5,6), List(7,8,9) ).transpose.map(x => x.sum/x.size.toDouble)
>res: List[Double] = List(4.0, 5.0, 6.0)

答案 1 :(得分:1)

@marios的答案很好,但如果子列表长度不一样怎么办?在这种情况下,transpose将抛出:

  

java.lang.IllegalArgumentException:transpose需要所有集合   具有相同的大小

假设您仍然想要所有第n个值的平均值,即使并非所有子列表都有n个元素,这也应该有效。

def getAvgs(lli: List[List[Int]]): List[Double] =
  if (lli.isEmpty) Nil
  else {
    val heads = lli.flatMap(_.headOption)
    heads.sum.toDouble / heads.length :: getAvgs(lli.filter(_.length > 1).map(_.tail))
  }

getAvgs(List(List(20,2,3,7), List(3,4), List(4,6,10)))
// res0: List[Double] = List(9.0, 4.0, 6.5, 7.0)

答案 2 :(得分:1)

val listOfLists = List( List(1,2,3), List(4,5,6), List(7,8,9) )
// listOfLists: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))

// if you wanted a simple avg
val listOfAvg = listOfLists.map(list => list.sum.toDouble / list.length)
// listOfAvg: List[Double] = List(2.0, 5.0, 8.0)

假设您希望获得i个元素的平均值,

val listOfIthAvg = listOfLists
  .flatMap(list => list.zipWithIndex)
  .groupBy({ case (i, index) => index })
  .map({ case (index, group) =>
    (index, group.map(_._1).sum.toDouble / group.length)
  })
  .toList
  .sortBy({ case (index, average) => index })
  .map({ case (index, average) => average })

答案 3 :(得分:0)

使用scala列表(Rubio的回答是动态的):

scala> val dl =List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11, 12))
scala> dl.transpose.map(_.sum/dl.length)
res5: List[Int] = List(5, 6, 7)

在Spark中使用Scala:

val valRDD = sc.parallelize(List((1,2,3), (4,5,6), (7,8,9)))
valRDD.map(x =>  (1, (x._1, x._2, x._3, 1)))
    .reduceByKey( (x,y) => (x._1+y._1, x._2+y._2, x._3+y._3, x._4+y._4) )
    .map(x=> ((x._2._1/x._2._4), (x._2._2/x._2._4), (x._2._3/x._2._4)))
    .take(5).foreach(println)

输出:(4,5,6)