如何压扁列表[任何]?

时间:2014-12-28 19:13:07

标签: scala

在Scala中,你怎么能把它弄平:

List(1, List(2, 3), 4, List(5, 6, 7))

进入这个

List(1, 2, 3, 4, 5, 6, 7)

3 个答案:

答案 0 :(得分:4)

scala99 problems

的一般解决方案
def flatten(ls: List[Any]): List[Any] = ls flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}                                               //> flatten: (ls: List[Any])List[Any]

flatten(List(1, List(2,3), 4, List(5,6,7)))     //> res0: List[Any] = List(1, 2, 3, 4, 5, 6, 7)

答案 1 :(得分:3)

如果必须处理Any,可以在运行时通过模式匹配来实现:

def flatten(l: List[_]): List[Any] = l flatMap {
  case m: List[_] => flatten(m)
  case e => List(e)
}

但是正如@Erik所说,最好一直跟踪类型信息,以便确保正确处理所有案例。对于Erik解决方案的更一般版本,您可以使用无形:https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/flatten.scala(该示例使用元组,但同样的方式与HList s的工作方式相同

答案 2 :(得分:-2)

您应该使用Either[Int, List[Int]]列表:

val xs: List[Either[Int, List[Int]]] = List(Left(1), Left(2), Right(List(1, 2, 3)), Left(7))
val xs1 = xs.flatMap {
  case Left(i)   => List(i)
  case Right(is) => is
}

另一方面,您可以通过不首先生成这样的异类列表来解决问题。

可选

使用Scalaz的\/,将Either[Int, List[Int]]替换为Int \/ List[Int]

val xs: List[Int \/ List[Int]] = ...

val xs1 = xs.map {
  case -\/(i)  => ...
  case \/-(is) => ...
}