Подтвердить что ты не робот

Scala: как преобразовать элементы кортежа в списки

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

val tuples = listOfStrings.map(string => {
            val split = string.split(":")
            (split(0), split(1), split(2))
        })

Я хотел бы получить split (0) в списке, split (1) в другом списке и так далее. Простым способом это может быть достигнуто, написав:

list1 = tuples.map(x => x._1).toList
list2 = tuples.map(x => x._2).toList
list3 = tuples.map(x => x._3).toList

Существует ли более элегантный (функциональный) способ достижения вышеуказанного без написания трех отдельных утверждений?

4b9b3361

Ответ 1

Это даст вам результат в виде списка:

tuples.map{t => List(t._1, t._2, t._3)}.transpose

Если вы хотите сохранить их в локальных переменных, просто выполните:

val List(l1,l2,l3) = tuples.map{t => List(t._1, t._2, t._3)}.transpose

UPDATE. Как указано Blaisorblade, стандартная библиотека на самом деле имеет встроенный метод для этого: unzip3, который похож на unzip, но на тройки вместо пар:

val (l1, l2, l3) = tuples.unzip3

Излишне говорить, что вы должны одобрить этот метод поверх моего ручного решения выше (но для кортежей arity > 3 это все равно будет применяться).

Ответ 2

Вы хотите разархивировать:

scala> val (numbers, homonyms) = List(("one", "won"), ("two", "too")).unzip
numbers: List[java.lang.String] = List(one, two)
homonyms: List[java.lang.String] = List(won, too)

Ответ 3

Если вы хотите что-то, что можно использовать для произвольных размеров кортежей:

val tupleSize = 3
0.until(tupleSize).toList
    .map(x => (_:Product).productElement(x).asInstanceOf[String])
    .map(tuples.map(_))

Очевидно, это можно было бы выразить более элегантно, если бы у вас был список массивов.

Ответ 4

Вы можете просто написать инструкции в одной строке.

Как

 (list1, list2, list3) = tuples.foldRight((List[String](), List[String](), List[String]()))( (a,b) => (a._1 :: b._1, a._2 :: b._2, a._3 :: b._3 ) )

Ответ 5

Я не знаю об элегантности, но вы можете сделать это в одной строке без промежуточного этапа хранения кортежей. Возможно, это немного трудно читать...

(for(split <- listOfStrings.map(_.split(":")))
  yield List(split(0), split(1), split(2))).transpose

пример репликации:

scala> listOfStrings
res1: List[java.lang.String] = List(a:b:c, d:e:f, g:h:i)

scala> (for(split <- listOfStrings.map(_.split(":")))
     |   yield List(split(0), split(1), split(2))).transpose
res2: List[List[java.lang.String]] = List(List(a, d, g), List(b, e, h), List(c, f, i))