Разделение списка на два списка в scala

У меня есть список, содержащий что-то вроде:

val lines: List[String] = List("bla blub -- id_1", "sdkfjdf -- id_2", "blubber blab -- id_1", "foo -- id_3", "ieriuer -- id_2", "bar -- id_3")

Таким образом, в основном список содержит идентификатор, который существует ровно дважды (id_x), и строку, которая принадлежит одному из идентификаторов.

Я хочу разделить этот список на два списка, каждый из которых содержит уникальный набор id_s с соответствующими строками, например:

l1("bla blub -- id_1", "sdkfjdf -- id_2", "foo -- id_3") 
l2("blubber blab -- id_1", "ieriuer -- id_2", "bar -- id_3")

Как мне это сделать функционально?

С уважением, Свен


person sveri    schedule 07.08.2013    source источник


Ответы (2)


lines.groupBy(_.split(" -- ")(1)).toList.map(_._2).transpose

Это грубый и готовый способ сделать это; на самом деле, если вы хотите сделать что-то еще с этими данными, вероятно, будет лучше проанализировать элементы в классе case, например:

case class Item(id: String, text: String)
val items = for {
  line <- lines
  Array(text, id) = line.split(" -- ")
} yield Item(id, text)

затем сделайте то же, что и выше, за исключением groupBy(_.id), а также sortBy(_.id).

person Luigi Plinge    schedule 07.08.2013
comment
Это работает, спасибо большое, я не знал о транспонировании. Однако знаете ли вы о версии, которая может быть парализована в списке? - person sveri; 08.08.2013
comment
lines.par.groupBy ... должен помочь. Однако не гарантируется, что это будет быстрее, особенно для небольших списков. - person Luigi Plinge; 08.08.2013

Как насчет этого решения?

lines.groupBy(_.takeRight(3)).map(_._2).foldLeft((List.empty[String], List.empty[String])) { 
  (acc, elem) => elem match {
    case left :: right :: Nil =>
      (left :: acc._1, right :: acc._2)
    case Nil => acc
  }
}

res2: (List[String], List[String]) = (List(bla blub -- id_1, sdkfjdf -- id_2, foo -- id_3),List(blubber blab -- id_1, ieriuer -- id_2, bar -- id_3))
person 4lex1v    schedule 07.08.2013