14

假设我有以下元组列表:

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

有没有更优雅(功能)的方式来实现上述目标,而无需编写 3 个单独的语句?

4

5 回答 5

13

这将为您提供作为列表列表的结果:

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

更新:正如 Blaisorblade 所指出的,标准库实际上有一个内置的方法:unzip3,这就像unzip但是对于三元组而不是对:

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

不用说,与我上面的手动解决方案相比,您应该更喜欢这种方法(但对于 arity > 3 的元组,这仍然适用)。

于 2012-09-12T16:42:20.647 回答
11

你想解压:

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)
于 2013-06-24T17:23:52.690 回答
3

如果你想要一些可以用于任意元组大小的东西:

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

显然,如果您有一个数组列表,则可以更优雅地表达这一点。

于 2012-09-12T17:01:32.120 回答
1

您可以将语句写在一行中。

 (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 ) )
于 2012-09-12T16:32:19.973 回答
0

我不知道优雅,但你可以在一行中完成,而无需存储元组的中间步骤。可能读起来有点难……

(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))
于 2012-09-12T16:53:20.770 回答