Outsider
Outsider

Reputation: 933

How to merge tuples by same elements in Scala

For example, if I have the following tuples:

(1, "a", "l")
(1, "a", "m")
(1, "a", "n")

I want to merge them like this:

(1, "a", List("l", "m", "n"))

In my case, the lists are a result from an inner join using Slick. So, the first and second elements (1 and "a") should be the same. If somebody knows how to merge like that in case of using Slick, let me know please.

Or more generally, the way to merge tuples with inner lists by the same elements.

(1, "a", "l")
(1, "a", "m")
(1, "b", "n")
(1, "b", "o")
// to like this
List( (1, "a", List("l", "m")), (1, "b", List("n", "o")) )

Upvotes: 9

Views: 2709

Answers (2)

gzm0
gzm0

Reputation: 14842

How about:

val l = ??? // Your list

val groups = l groupBy { case (a, b, c) => (a,b) }

val tups = groups map { case ((a,b), l) => (a,b,l.map(_._3)) }

tups.toList

Upvotes: 8

Beryllium
Beryllium

Reputation: 12998

You could try foldRight

val l = List((1, "a", "l"), (1, "a", "m"), (1, "a", "n"), (1, "b", "n"), (1, "b", "o"))
val exp = List((1, "a", List("l", "m", "n")), (1, "b", List("n", "o")))

val result = l.foldRight(List.empty[(Int, String, List[String])]) {
  (x, acc) =>
    val (n, s1, s2) = x

    acc match {
      case (n_, s1_, l_) :: t if (n == n_ && s1 == s1_) =>
        (n_, s1_, (s2 :: l_)) :: t

      case _ =>
        (n, s1, List(s2)) :: acc

    }
}

println(result)
println(result == exp)

Update

If the input list is not sorted:

val result = l.sorted.foldRight(...)

Upvotes: 1

Related Questions