Estoy trabajando en Scala a nivel principiante.

Tengo las siguientes listas

List_1=List((2.0,0), (4.5,1), (1.2,1), (3.0,3), (4.4,1), (4.5,0), (1.7,0), (5.3,2), (2.0,3))
List_2=List(0,1,2,3)

Quiero agregar todos los primeros valores de List_1 que están emparejados con números entre 0 y 3. Intenté (List_1.filter(_._2==0).map(e=>e._1)) y obtuve 2.0, 4.5 y 1.7 y su suma es 8.2. Repitiendo para 1,2,3 quiero obtener un resultado como este (8.2,10.1,5.3,5.0).
¿Alguien puede darme una idea para proceder?

0
cgt 14 sep. 2018 a las 19:09

3 respuestas

La mejor respuesta

De hecho, puedes escribirlo literalmente en scala:

(0 to 3).map { n => 
   list.collect { case (x, `n`) => x }.sum 
}

Tenga en cuenta los "backticks" alrededor de n en la cláusula case. Esto significa "hacer coincidir solo las tuplas donde el segundo elemento es igual a n". Sin backticks en este contexto, significaría "crear una nueva variable local n y asignarle el segundo elemento de la tupla".

Alternativamente, con un poco más de esfuerzo, podría calcular las cuatro sumas en una sola pasada por la lista (lo que podría ahorrarle algo de tiempo, si hubiera, por ejemplo, miles de sumas, en lugar de cuatro, y la lista tuviera algunos millones de elementos en eso):

list.foldLeft(Map.empty[Int, Double]) { case (result, (value, n)) => 
   result + (n -> (result.getOrElse(n, 0.0) + value))
}.toSeq
 .sortBy(_._1)
 .map(_._2)

Esto recorre la lista, resume los valores y acumula el resultado en un mapa, tecleado por el segundo elemento de la tupla. Luego convierta el mapa resultante en una secuencia de tuplas, ordénelo por clave y luego suéltelo, devolviendo solo un Seq de sumas.

1
Dima 15 sep. 2018 a las 20:59

Para hacer lo que necesita, puede usar groupBy

val list = List( (2.0,0), (4.5,1), (1.2,1), (3.0,3), (4.4,1), (4.5, 0), (1.7,0), (5.3,2), (2.0,3) )

val result = list.groupBy { case (_, key) => key }.toList.sortBy { case (key, _) => key }.map { case (_, values) => values.map { case (value, _) => value }.sum }

Primero agrupa por su clave (de 0 a 3), obtiene un Mapa [Int, List [(Double, Int)]. Luego puede ordenarlos por su clave (si desea ordenar su resultado), y finalmente transformar cada elemento en la suma de sus valores.

Este es el camino más corto, pero prefiero el primero (es más expresivo)

val r = list.groupBy(_._2).toList.sortBy(_._1).map(_._2.map(_._1).sum)
0
marc_s 7 oct. 2018 a las 09:20

Listas dadas:

val List_1 = List((2.0,0), (4.5,1), (1.2,1), (3.0,3), (4.4,1), (4.5,0), (1.7,0), (5.3,2), (2.0,3))
val List_2 = List(0,1,2,3)

Simplemente póngalos en for comprensión con pequeños cambios en su código como se muestra aquí:

for(i<-List_2) yield List_1.filter(_._2==i).map(e=>e._1).sum

O

List_2.map(i=>List_1.filter(_._2==i).map(e=>e._1).sum)

Y listo

En Scala REPL:

scala> for(i<-List_2) yield (List_1.filter(_._2==i).map(e=>e._1).sum)
res7: List[Double] = List(8.2, 10.100000000000001, 5.3, 5.0)
scala> List_2.map(i=>List_1.filter(_._2==i).map(e=>e._1).sum)
res10: List[Double] = List(8.2, 10.100000000000001, 5.3, 5.0)
0
RAGHHURAAMM 15 sep. 2018 a las 07:30