Как получить среднее значение для нескольких списков в Scala

#scala

#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) здесь.

Ответ №1:

Предполагая, что вам нужно среднее значение 1-го элемента, за которым следует среднее значение всего 2-го элемента и т. Д:

 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. почему вы хотите ввести ограничение транспонирования… также откуда вы знаете, что списки имеют длину 3?

2. Почему, по вашему мнению, транспонирование является ограничением?

3. Верно, длина 3 была неправильной. Транспонирование — это здорово, если вы знаете, что списки имеют одинаковую длину. Если нет, то то, что есть у @jwvh, является более полным.

Ответ №2:

Ответ от @marios хороший, но что, если вложенные списки не имеют одинаковой длины? В этом случае transpose будет выброшен:

java.lang.Исключение IllegalArgumentException: для транспонирования требуется, чтобы все коллекции имели одинаковый размер

Предполагая, что вам все еще нужно среднее значение всех 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)
  

Комментарии:

1. Разве вы не можете просто сопоставить эти списки с суммой и разделить на длину? Зачем нужен этот код?

2. @SarveshKumarSingh, посмотрите еще раз на вопрос и на ответ Мариоса. OP хочет получить среднее значение всех 1-х элементов из каждого вложенного списка, а также всех 2-х элементов, 3-х элементов и т.д. Мое предлагаемое решение обеспечивает среднее значение для всех N-х элементов, даже если не все вложенные списки имеют N элементов. В моем примере вывода есть только один 4-й элемент, поэтому усреднение всех 4-х элементов приводит 7/1 = 7.0 к.

Ответ №3:

 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 элементов th,

 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 })
  

Ответ №4:

Использование списков scala (ответ Рубио должен быть динамическим):

 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)
  

Использование Scala в Spark:

 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)

Комментарии:

1. Я не думаю, что OP запрашивает искровое решение