#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 запрашивает искровое решение