Как объединить кортежи по одним и тем же элементам в Scala

Например, если у меня есть следующие кортежи:

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

Я хочу объединить их так:

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

В моем случае списки являются результатом внутреннего соединения с использованием Slick. Итак, первый и второй элементы (1 и "a") должны быть одинаковыми. Если кто-то знает, как так слить в случае использования Slick, дайте мне знать, пожалуйста.

Или, в более общем смысле, способ объединения кортежей с внутренними списками по одним и тем же элементам.

(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")) )

person Outsider    schedule 04.06.2013    source источник
comment
Какой результат вы ожидаете, если у вас есть случай с кортежами (1, a, m) и (2, a, l)?   -  person 4lex1v    schedule 04.06.2013


Ответы (2)


Как насчет:

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
person gzm0    schedule 04.06.2013

Вы можете попробовать 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)

Обновить

Если входной список не отсортирован:

val result = l.sorted.foldRight(...)
person Beryllium    schedule 04.06.2013
comment
Это будет работать только в том случае, если все кортежи отсортированы, как в приведенном выше примере. Если бы четыре кортежа были расположены по-разному, это решение не соответствовало бы - person Jatin; 04.06.2013
comment
Данные поступают из базы данных, поэтому они должны быть отсортированы по базе данных. В любом случае, на всякий случай, я добавил обновление. - person Beryllium; 04.06.2013
comment
Я узнал из вашего кода. но я думаю, что ответ gzm0 более общий. Кстати, спасибо @Beryllium. - person Outsider; 05.06.2013
comment
Не за что, это нормально. Я согласен, что это более общий способ. Если у вас большое количество строк, и вы все равно рано или поздно сортируете, всегда есть foldRight. Это может быть интересно, здесь я узнал о foldRight. - person Beryllium; 05.06.2013