如何在Scala中轻松地将IndexedSeq [Array [Int]]转换为Seq [Seq [Int]]?

时间:2015-08-30 23:47:56

标签: scala collections type-conversion

我有一个函数,它接受一个整数列表列表,特别是Seq[Seq[Int]]。然后我通过阅读文本文件并使用split生成此数据,并生成Array列表。 Scala不承认这一点,他提出了一个匹配错误。但是IndexedSeqArray单独使用Seq[Int]函数就可以了,显然​​只有嵌套集合才是问题。我如何隐式地将IndexedSeq[Array[Int]]转换为Seq[Seq[Int]],或者除了使用toList之外我还能如何做到这一点,如下所示?例如,Iterable[Iterable[Int]]似乎很好,但我不能使用它。

scala> def g(x:Seq[Int]) = x.sum
g: (x: Seq[Int])Int

scala> g("1 2 3".split(" ").map(_.toInt))
res6: Int = 6

scala> def f(x:Seq[Seq[Int]]) = x.map(_.sum).sum
f: (x: Seq[Seq[Int]])Int

scala> f(List("1 2 3", "3 4 5").map(_.split(" ").map(_.toInt)))
<console>:9: error: type mismatch;
 found   : List[Array[Int]]
 required: Seq[Seq[Int]]
              f(List("1 2 3", "3 4 5").map(_.split(" ").map(_.toInt)))
                                          ^

scala> f(List("1 2 3", "3 4 5").map(_.split(" ").map(_.toInt).toList))
res8: Int = 18

3 个答案:

答案 0 :(得分:2)

问题是Array没有实现SeqLike。通常,对ArrayOps中定义的WrappedArrayscala.predef的隐式转换允许使用类似Seq的数组。但是,在您的情况下,数组作为泛型参数从隐式转换中“隐藏”。一种解决方案是提示编译器,您可以将隐式转换应用于通用参数,如下所示:

def f[C <% Seq[Int]](x:Seq[C]) = x.map(_.sum).sum

这与保罗上面的回应类似。问题是在Scala 2.11中不推荐使用视图边界,并且使用已弃用的语言功能并不是一个好主意。幸运的是,视图边界可以重写为上下文边界,如下所示:

 def f[C](x:Seq[C])(implicit conv: C => Seq[Int]) = x.map(_.sum).sum

现在,假设存在从CSeq[Int]的隐式转换,它实际上存在于predef中。

答案 1 :(得分:1)

这个怎么样:

implicit def _convert(b:List[Array[Int]]):Seq[Seq[Int]]=b.map(_.toList)

答案 2 :(得分:1)

重新定义f更灵活。

由于Traversable是List,Seq,Array等的父级,因此如果它基于Traversable,则f将与这些容器兼容。 Traversable有sum,flatten和map,这就是所需要的。

这是多么棘手的是

stack install package_name

是挑剔的,并且不会对def f(y:Traversable[Traversable[Int]]):Int = y.flatten.sum 类型的y工作,尽管它适用于List[Array[Int]]

为了减少挑剔,一些类型的视图边界将起作用。

最初,我用flatten / sum操作替换了你的总和。

Array[List[Int]]

我发现这似乎也有效,但我没有进行太多测试:

def f[Y<%Traversable[K],K<%Traversable[Int]](y:Y):Int=y.flatten.sum

def f[Y <% Traversable[K], K <% Traversable[Int]](y:Y):Int=y.map(_.sum).sum 语法将Y viewable表示为某些类型K的Traversable [K],可以作为Int的遍历进行查看。

定义一些不同的容器,包括您需要的容器:

<%

测试:

scala> val myListOfArray = List(Array(1,2,3),Array(3,4,5))
val myListOfArray = List(Array(1,2,3),Array(3,4,5))
myListOfArray: List[Array[Int]] = List(Array(1, 2, 3), Array(3, 4, 5))

scala> val myArrayOfList = Array(List(1,2,3),List(3,4,5))
val myArrayOfList = Array(List(1,2,3),List(3,4,5))
myArrayOfList: Array[List[Int]] = Array(List(1, 2, 3), List(3, 4, 5))

scala> val myListOfList = List(List(1,2,3),List(3,4,5))
val myListOfList = List(List(1,2,3),List(3,4,5))
myListOfList: List[List[Int]] = List(List(1, 2, 3), List(3, 4, 5))

scala> val myListOfRange = List(1 to 3, 3 to 5)
val myListOfRange = List(1 to 3, 3 to 5)
myListOfRange: List[scala.collection.immutable.Range.Inclusive] = List(Range(1, 2, 3), Range(3, 4, 5))