我有一个有趣的问题,对Scala的新手来说很难证明
我需要结合两个列表:
listA : List[List[Int]]
listB : List[Int]
以下列方式:
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)
在Java中,我会使用几个嵌套循环:
for(List<Integer> list : listA) {
for(Integer i: listB) {
subList = new ArrayList<Integer>(list);
subList.add(i);
listC.add(subList);
}
}
我猜这是Scala中的一个内容,但到目前为止它还在逃避我。
答案 0 :(得分:9)
您想要执行扁平笛卡尔积。 For-comprehensions是最简单的方法,可能看起来与您的Java解决方案类似:
val listC = for (list <- listA; i <- listB) yield list :+ i
答案 1 :(得分:7)
scand1sk的answer几乎肯定是你应该在这里使用的方法,但作为旁注,还有另一种思考这个问题的方法。你正在做的是将
import scalaz._, Scalaz._
val listC = (listA |@| listB)(_ :+ _)
我们可以将(_ :+ _)
视为一个获取事物列表的函数,以及一个相同类型的函数,并返回一个新列表:
(_ :+ _): ((List[Thing], Thing) => List[Thing])
Scalaz为列表提供了一个applicative functor实例,因此我们实际上可以创建一个新函数,为上面的每个类型添加一个额外的列表层。奇怪的(x |@| y)(_ :+ _)
语法说:创建这样一个函数并将其应用于x
和y
。结果就是你要找的东西。
与for-comprehension案例一样,如果你不关心秩序,你可以通过使用::
并翻转参数的顺序来提高操作效率。
有关详细信息,请参阅我在Haskell中有关笛卡尔积的相似答案here,Scala中的这个introduction to applicative functors或this blog post关于使此类事情的语法少一些斯卡拉丑陋。如果你不在乎,当然可以随意忽略上述所有内容。