Reputation: 1
I am working on Scala at a beginner level.
I have the following lists
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)
I want to add all first values from List_1 which are paired with numbers between 0 and 3. I tried (List_1.filter(_._2==0).map(e=>e._1))
and get 2.0, 4.5 and 1.7 and their sum is 8.2. By repeating for 1,2,3 i want to get a result like this (8.2,10.1,5.3,5.0)
.
Can anybody give me an idea to proceed?
Upvotes: 0
Views: 88
Reputation: 1428
In order to do what you need you can use 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 }
First you group by your key (from 0 to 3), you get a Map[Int, List[(Double, Int)]. Then you can sort them by your key (if you want your result ordered), and finally transform each element in the sum of its values.
This is a shortest way but I prefer the first one (it is more expressive)
val r = list.groupBy(_._2).toList.sortBy(_._1).map(_._2.map(_._1).sum)
Upvotes: 0
Reputation: 40510
You can actually write it quite literally in scala:
(0 to 3).map { n =>
list.collect { case (x, `n`) => x }.sum
}
Note the "backticks" around n
in the case
clause. This means "match only tuples where second element equals to n
". Without backticks in this context, it would mean "create a new local variable n
, and assigned the second element of the tuple to it".
Alternatively, with a little more effort, you could compute all four sums in one pass through the list (which could save you some time, if there were, say, thousand of sums, rather than four, and the list had a few million elements in it):
list.foldLeft(Map.empty[Int, Double]) { case (result, (value, n)) =>
result + (n -> (result.getOrElse(n, 0.0) + value))
}.toSeq
.sortBy(_._1)
.map(_._2)
This goes through the list, summing up values, and accumulating the result in a map, keyed by the second element of the tuple.
Then convert the resulting map to a sequence of tuples, sort it by key, and then drop it, returning just a Seq
of sums.
Upvotes: 1
Reputation: 1099
Given Lists:
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)
Just put them in for
comprehension with little changes in your code as shown here:
for(i<-List_2) yield List_1.filter(_._2==i).map(e=>e._1).sum
or
List_2.map(i=>List_1.filter(_._2==i).map(e=>e._1).sum)
and you are done.
In 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)
Upvotes: 0