在Scala中展平元组列表?

Ric*_*zaк 4 scala tuples list flatten

我原以为可以很容易地将元组列表弄平:

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
Run Code Online (Sandbox Code Playgroud)

但相反,这发生了:

<console>:15: error: No implicit view available from (Char, Char) => scala.collection.GenTraversableOnce[B].
       pq.flatten
          ^
Run Code Online (Sandbox Code Playgroud)

我可以完成工作:

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)
Run Code Online (Sandbox Code Playgroud)

但我不理解错误信息.而我的替代解决方案似乎错综复杂且效率低下.

该错误消息的含义是什么?为什么我不能简单地展平元组列表?

jwv*_*wvh 13

如果找不到隐式转换,您可以显式提供.

pq.flatten {case (a,b) => List(a,b)}
Run Code Online (Sandbox Code Playgroud)

如果在整个代码中多次执行此操作,那么您可以通过使其隐式来保存一些样板.

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)
Run Code Online (Sandbox Code Playgroud)

  • 当源类型和目标类型都很常见时,请不要使用隐式转换.将其与例如自动拼图相混合,你会得到各种古怪的东西.有一个方法,需要一个字符串列表?突然``foo("a","b")`有效,但`foo("a","b","c")`却没有.并且...... (2认同)
  • 采取的点.从本质上讲,暗示有点太"怪异",在这样的偶然情况下可能应该避免. (2认同)

mdm*_*mdm 5

jwvh 的回答很好地涵盖了您问题的“编码”解决方案,因此我不打算详细介绍。我唯一想补充的是澄清为什么需要你和 jwvh 找到的解决方案。

正如 Scala 库中所述,Tuple2(,)转换为)是:

2 个元素的元组;a 的规范表示Product2

并跟进:

Product2 是 2 个分量的笛卡尔积。

......其手段Tuple2[T1,T2]代表:

所有可能的元素对的集合,其组件是两个集合的成员(分别为T1和 中的所有元素T2

List[T],在另一方面,表示的有序集合T的元素。

所有这一切实际上意味着没有绝对的方法将任何可能的转换Tuple2[T1,T2]为 aList[T],仅仅因为T1T2可能不同。例如,采用以下元组:

val tuple = ("hi", 5)
Run Code Online (Sandbox Code Playgroud)

这样的元组怎么会变平?应该5做一个String吗?或者也许只是扁平化为List[Any]? 虽然这两种解决方案都可以使用,但它们都是围绕类型系统工作的,因此它们不是Tuple按设计在API 中编码的。

所有这一切都归结为这样一个事实,即对于这种情况没有默认的隐式视图,您必须自己提供一个,因为jwvh和您都已经知道了。

  • @dima,另外,你可以让`Tuple[T,T]` 成为一个特定的monad 实例,但是为什么语言设计者会选择`List((5,7),(6,8))` 应该扁平化为`List (5,7,6,8)` 而不是,例如,`List(5,6)`?或者也许是`List(7,8)`?您描述的行为只有在您使用 `Tuple` 作为 `List` 时才是“明显的”,你不能期望类型系统理所当然地给予。 (3认同)