Reputation: 1247
Coming to Scala from R (complete newbie).
Say I have two lists:
val index = List(0,0,1,0,1)
val a = List(1,2,3,4,5)
Then index
can define a natural map from a
to b: List[List[Int]]
:
1 -> b(0)
2 -> b(0)
3 -> b(1)
4 -> b(0)
5 -> b(1)
So that:
b = List(List(1,2,4), List(3,5))
In general, given index
and a
, what is the most natural way to create b
in Scala?
e.g. in R I could for example write:
run_map <- function(index, a) {
map <- function(data, i) {
data[[i]] <- a[which(index == i)]
data
}
Reduce(map, unique(index), list())
}
Cheers for any help!
Upvotes: 2
Views: 503
Reputation: 16422
0) Given:
val index = List(0,0,1,0,1)
val a = List(1,2,3,4,5)
Here is an "iterative" way to arrive at the solution:
1) "Zip" 2 lists together to produce a list of pairs:
index.zip(a)
result:
List[(Int, Int)] = List((0,1), (0,2), (1,3), (0,4), (1,5))
2) Group by first element of the pair in the list.
index.zip(a).groupBy(_._1)
result:
Map[Int,List[(Int, Int)]] = Map(1 -> List((1,3), (1,5)), 0 -> List((0,1), (0,2), (0,4)))
3) Remove redundant index by projecting only second element from each pair in the list v
:
index.zip(a).groupBy(_._1).map{ case (i, v) => (i, v.map(_._2)) }
result:
Map[Int,List[Int]] = Map(1 -> List(3, 5), 0 -> List(1, 2, 4))
Upvotes: 4
Reputation: 35990
If you want one list to contain the index and the other list to contain the values then you would zip
them together:
val myMap = (a zip b).toMap
where a
contains the index and b
the values.
However, if there's duplicate indexes then you would want to do the following:
for{
(i, list) <- (a zip b) groupBy (_._1)
} yield (i, list map (_._2))
wherein you're zipping, grouping by the index and then mapping over the values in the list. That created list contains both the index and value as a tuple.
Upvotes: 4