Как объединить элемент списка, где каждый элемент списка имеет три кортежа? - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть это:

List(List("King",List("134"),"USA"),List("King",List("151","130"),"USA"))

Я хочу это наконец:

List("King",List("134","151","130"),"USA") 

1 Ответ

0 голосов
/ 06 февраля 2020

Для этого конкретного варианта использования вы можете использовать Pattern Matching:

val doubleList = List(List("King",List("134"),"USA"), List("King",List("151","130"),"USA"))
doubleList match {
  case (a :: (b:List[_]) :: c :: _) :: (_ :: (d:List[_]) :: _) :: _ => a :: (b ++ d) :: c :: Nil
  case other => println(s"Not expected: $other")
}

Как вы можете видеть, это не так красиво, но с лучшими именами это может работать для вас.

Вот некоторые объяснения:

  • a::b::c представляет список, где a и b - первые два элемента, а c - остаток (хвост)

  • _ - это значения, которые вас не интересуют, в нашем случае хвосты и тип списка.

  • , остальные составляют ваши списки, и результат объединяет оба подсписка.

Результат, как и ожидалось:

List(King, List(134, 151, 130), USA)

Как указано в комментариях, вы должны изменить структуру данных, если можете.

Тогда это было бы проще. Например:

case class MyObj(name: String, indices: List[String], country: String) {

  def merge(other: MyObj): MyObj =
     copy(indices = indices ++ other.indices)
}

val obj1 = MyObj("King",List("134"),"USA")
obj1.merge(MyObj("King",List("151","130"),"USA"))

Это лучше читать.

Обновление : Решение для комментария:

Вы можете использовать groupBy а затем с помощью flatMap объединить внутренние списки:

 st.groupBy(e => (e._1, e._3))   // -> Map((COOK,ENG) -> List((COOK,List(100),ENG), ...)
    .map{ case ((n, c), list) => (n, list.flatMap(_._2), c)}
    .toList
    .sortBy(_._1)

Возвращается, как и ожидалось: List((COOK,List(100, 125, 135, 145),ENG), (KIM,List(115, 134, 148, 154),AUS), (TIM,List(102, 105),ZIM), (VIR,List(115, 120, 134),IND))

_._1 - это способ доступа к записям кортежа.

Обновление 2 : Продолжить сортировку

Это возможно, но AFAIK становится сложным. Я не уверен, что это достаточно читабельно:

st
  .zipWithIndex // add an index for later sorting
  .groupBy { case (e, _) => (e._1, e._3) }
  .map { case ((n, c), groupedList) => (n,
    groupedList.map { case (trible, index) => (trible._2, index) } // you are only interested in the list and the index
      .foldLeft((List.empty[String], Int.MaxValue)) { case ((list1, i1), (list2, i2)) =>
        (list1 ++ list2, Math.min(i1, i2)) // fold over all the lists and take the minimal index
      }
    , c)
  }.toList
  .sortBy { case (_, (_, index), _) => index } // sort the result by the index
  .map { case (n, (list, _), c) => (n, list, c) } // get rid of the index
...