Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort two lists together in scala

Say I have two lists:

List(("a",1),("b",4),("d",5),("a",7),("b",6)) 

and

List("a","b","c","d")

and I want to group them based on the first list such that I get:

List("a" -> List(("a",1),("a",7)), "b" -> List(("b",4),("b",6)), "d" -> List(("d",5)))

What would be the best way to achieve this? I know I can use groupBy and pattern match against pre-determined values but when the second list is not pre-determined I get a little stuck.

Edit:

I need a copy of the object in the second list as the key for the processed list. I might need to group by a parameter of an on object in the second list but still maintain the entire object as the key... if that makes sense.

List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
List(("a",1,1),("b",2,3),("c",5,6),("d",6,7))

becomes:

 List(("a",1,1) -> List(("a",1),("a",7)), ("b",2,3) -> List(("b",4),("b",6)), ("d",6,7) -> List(("d",5)))

Sorry for lack of clarity!

like image 666
Alex Avatar asked Jan 15 '23 22:01

Alex


2 Answers

Per your edit, with a for-comprehension:

for {
  key <- second
  pair <- first.groupBy(_._1).get(key)
} yield key -> pair

Or the unsugared equivalent:

second.flatMap(key => first.groupBy(_._1).get(key).map(key -> _))

Both of these perform the groupBy operation for every key. If this is an issue you can of course avoid it with the slightly more verbose:

val mappings = first.groupBy(_._1)
second.flatMap(key => mappings.get(key).map(key -> _))

And to address your new edit: if you need to transform each item in the second list to use it as a key for the first, there are a couple of ways you can go about that. For example, given:

val first = List(("a", 1), ("b", 4), ("d", 5), ("a", 7), ("b", 6))
val second = List(("a", 1, 1), ("b", 2, 3), ("c", 5, 6), ("d", 6, 7))

Either:

for {
  item @ (key, _, _) <- second
  pair <- first.groupBy(_._1).get(key)
} yield item -> pair

Or:

for {
  item <- second
  pair <- first.groupBy(_._1).get(item._1)
} yield item -> pair

Works as desired.

like image 114
Travis Brown Avatar answered Jan 21 '23 14:01

Travis Brown


The solution is surprisingly simple:

first groupBy(_._1) toList

Result:

List((a,List((a,1), (a,7))), (d,List((d,5))), (b,List((b,4), (b,6))))

Where first is your first list (what is the purpose of the second one)?

like image 29
Tomasz Nurkiewicz Avatar answered Jan 21 '23 14:01

Tomasz Nurkiewicz