我原本以为可以很容易地将元组列表弄平:
scala> val p = "abcde".toList
p: List[Char] = List(a, b, c, d, e)
scala> val q = "pqrst".toList
q: List[Char] = List(p, q, r, s, t)
scala> val pq = p zip q
pq: List[(Char, Char)] = List((a,p), (b,q), (c,r), (d,s), (e,t))
scala> pq.flatten
但相反,会发生这种情况:
<console>:15: error: No implicit view available from (Char, Char) => scala.collection.GenTraversableOnce[B].
pq.flatten
^
我可以完成工作:
scala> (for (x <- pq) yield List(x._1, x._2)).flatten
res1: List[Char] = List(a, p, b, q, c, r, d, s, e, t)
但我不理解错误信息。而我的替代解决方案似乎错综复杂且效率低下。
该错误消息的含义是什么?为什么我不能简单地展平元组列表?
答案 0 :(得分:12)
如果无法找到隐式转化,您可以明确提供。
pq.flatten {case (a,b) => List(a,b)}
如果在整个代码中多次执行此操作,则可以通过隐藏来保存一些样板文件。
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit def flatTup[T](t:(T,T)): List[T]= t match {case (a,b)=>List(a,b)}
flatTup: [T](t: (T, T))List[T]
scala> pq.flatten
res179: List[Char] = List(a, p, b, q, c, r, d, s, e, t)
答案 1 :(得分:4)
jwvh的答案涵盖&#34;编码&#34;完全解决你的问题,所以我不打算详细介绍。我想要添加的唯一内容是澄清为什么您和jwvh都需要的解决方案。
如Scala图书馆所述,Tuple2
((,)
转换为)是:
2个元素的元组;
Product2
的规范表示。
跟进:
Product2
是2个组件的笛卡尔积。
... Tuple2[T1,T2]
代表的means:
所有可能的元素对的集合,其组件是两个集合的成员(分别为
T1
和T2
中的所有元素)。
另一方面,List[T]
表示T
元素的有序集合。
所有这一切实际上意味着没有绝对的方式将任何可能的Tuple2[T1,T2]
转换为List[T]
,只是因为 T1
和T2
可能不同。例如,采用以下元组:
val tuple = ("hi", 5)
这样的元组怎么可能被夷为平地? 5
应该String
吗?或者可能只是展平到List[Any]
?虽然可以使用这两种解决方案,但它们围绕类型系统工作,因此它们不是按照设计在Tuple
API中编码的。
所有这一切都归结为这种情况没有默认的隐式视图,你必须自己提供一个,因为 jwvh 并且你已经想到了。
答案 2 :(得分:0)
我们最近需要这样做。在介绍我们的解决方案之前,请允许我简要解释一下用例。
给定一个项目池(我将其称为类型 T
),我们希望针对池中的所有其他项目对每个项目进行评估。这些比较的结果是 Set
个失败的评估,我们将其表示为所述评估中左项和右项的元组:(T, T)
。
一旦这些评估完成,我们就可以将 Set[(T, T)]
展平为另一个 Set[T]
,突出显示所有未通过任何比较的项目。
我们对此的解决方案是折叠:
val flattenedSet =
set.foldLeft(Set[T]())
{ case (acc, (x, y)) => acc + x + y }
这以一个空集(foldLeft
的初始参数)作为累加器开始。
然后,对于这里消耗的Set[(T, T)]
(命名为set
)中的每个元素,都会传递fold函数:
acc
),以及(T, T)
元组,case
将其解构为 x
和 y
。我们的 fold 函数然后返回 acc + x + y
,它返回一个包含累加器中除 x
和 y
之外的所有元素的集合。该结果作为累加器传递给下一次迭代——因此,它累加每个元组内的所有值。
我特别喜欢这个解决方案,因为它避免在进行展平时创建中间 List
- 相反,它在构建新的 Set[T]
时直接解构每个元组。
我们也可以更改我们的评估代码,以返回包含每次失败评估中左右项目的 List[T]
- 那么 flatten
就是 Just Work™。但我们认为元组更准确地代表了我们的评估目标——特别是一个项目与另一个项目的对比,而不是可以想象代表任意数量项目的开放式类型。