在Scala中,有没有一种简洁的方法将两个元组合并成一个较大的元组?

19

假设我有以下元组:

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)

有没有一种友好的方法将它们组合起来(如果需要,分两步进行),并形成一个Tuple7?我真正寻求的是将任意长度的元组组合在一起的通用答案,并意识到由于元组大小的限制,存在一些限制。我特别想要一个元组结果,而不是一个集合。


2
查看各种形式的HLists: https://github.com/harrah/up http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/ https://dev59.com/YF3Ua4cB1Zd3GeqP9A8C#8067456 - Owen
2个回答

16

Shapeless 需要依赖方法类型 (-Ydependent-method-types),我希望能够下载适用于 2.9.1 的二进制文件,以便尝试,但它真的非常优美。根据这个单元测试,它可以像这样应用于您的情况:

import shapeless.Tuples._
import shapeless.HList._
val t7 = (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled

尽管Miles表明不能保证支持,但它实际上有单元测试,并且源代码在GitHub上具有开源许可证,所以至少它不仅仅是博客文章中的实验。

编辑:像广告一样工作-编译需要一些时间,我必须向sbt添加-Xss1m

$ scala -Ydependent-method-types -cp target/scala-2.9.1/shapeless_2.9.1-1.1.0.jar
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import shapeless.Tuples._
import shapeless.Tuples._

scala> import shapeless.HList._
import shapeless.HList._

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)

scala> (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled
res0: (java.lang.String, java.lang.String, Int, java.lang.String, java.lang.String,
java.lang.String, java.lang.String) = (abcd,efg,1234,lmnop,qrs,tuv,wxyz)

在某个时候,我可能会直接将HList风格的操作升级到元组上,这样你就可以跳过列表和元组之间的转换,直接编写t1 ::: t2 ::: t3。我已经在topic/tuples分支上进行了尝试,但在提交之前,我想确保额外的隐式不会引起混乱。 - Miles Sabin
是的,这正是我在寻找的。感谢huynhjl指出并展示它满足问题的工作,也感谢Miles编写如此酷的软件包! - jxstanford
单元测试的链接已经不存在了。这是哪个版本的Shapeless?在Scala 2.11版本中,我找不到“import shapeless.Tuples._”这个东西。 - Adrian

6

如果所有元素的类型都相同,您真的需要在这里使用集合。您可以轻松将元组合并为一个List

def combine(xss: Product*) = xss.toList.flatten(_.productIterator)

使用您的例子:

scala> combine(t1, t2, t3)
res1: List[Any] = List(abcd, efg, hijk, lmnop, qrs, tuv, wxyz)

试图将此转换回元组是不行的,因为您的转换方法(例如,通过模式匹配)无法返回特定的元组类型(方法的返回类型是什么?),并且每个元素的类型信息已经丢失。


4
我应该给出一个更好的例子。并不能保证元组的所有成员都是相同类型的,我特别寻找一种获取新元组的方法。在其他情况下,我会使用集合,但在这种情况下,答案需要一个元组。我已经修改了问题... - jxstanford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接