我有一个有趣的问题,对Scala新手来说很难证明.
我需要结合2个列表:
listA : List[List[Int]]
listB : List[Int]
Run Code Online (Sandbox Code Playgroud)
通过以下方式:
val listA = List(List(1,1), List(2,2))
val listB = List(3,4)
val listC = ???
// listC: List[List[Int]] = List(List(1,1,3),List(1,1,4),List(2,2,3),List(2,2,4)
Run Code Online (Sandbox Code Playgroud)
在Java中,我会使用几个嵌套循环:
for(List<Integer> list : listA) {
for(Integer i: listB) {
subList = new ArrayList<Integer>(list);
subList.add(i);
listC.add(subList);
}
}
Run Code Online (Sandbox Code Playgroud)
我猜这是Scala中的一个班轮,但到目前为止它还在逃避我.
您想要执行扁平的笛卡尔积.For-comprehensions是最简单的方法,可能看起来与您的Java解决方案类似:
val listC = for (list <- listA; i <- listB) yield list :+ i
Run Code Online (Sandbox Code Playgroud)
scand1sk的答案几乎肯定是你应该在这里使用的方法,但作为旁注,还有另一种思考这个问题的方法.你正在做的是将附加操作提升到列表的applicative functor中.这意味着使用Scalaz可以编写以下内容:
import scalaz._, Scalaz._
val listC = (listA |@| listB)(_ :+ _)
Run Code Online (Sandbox Code Playgroud)
我们可以想到 (_ :+ _)视为一个函数,它接受一个事物列表和一个相同类型的单个事物,并返回一个新列表:
(_ :+ _): ((List[Thing], Thing) => List[Thing])
Run Code Online (Sandbox Code Playgroud)
Scalaz为列表提供了一个applicative functor实例,因此我们实际上可以创建一个新函数,为上面的每个类型添加一个额外的列表层.奇怪的(x |@| y)(_ :+ _)语法说:创建这样一个函数并将其应用于x和y.结果就是你要找的东西.
而在for-comprehension案例中,如果您不关心顺序,则可以通过使用::和翻转参数的顺序来提高操作效率.
有关更多信息,请参阅我在此类似的答案,关于Haskell中的笛卡尔积,Scala中的应用函子的介绍,或者这篇关于在Scala 中使这种事情的语法稍微不那么难看的博客文章.如果你不在乎,当然可以随意忽略上述所有内容.
| 归档时间: |
|
| 查看次数: |
626 次 |
| 最近记录: |