由于这个问题专门针对Scala编程语言,因此Java中的解决方案也可以。然而,需要注意的一个小问题是,在Scala解决方案中tail recursion(Scaladocs)绝对优于其他解决方案,而在Java中,非递归解决方案是有利的。这是因为它需要在相当大的数据结构上工作,以便每个项目包含在"最好是懒惰的流或类似的"可以相应地处理,而不会收到StackOverflowError(Javadocs)(多么具有讽刺意味)。
应该置换的数据类型是Scala List(Scaladoc),但是使用Java数组和一个有点错综复杂的循环结构来回应完全没问题。
在Scala中,以下是检索给定集合类型的所有排列的完全有效的方法。以下方法以惰性方式返回包含所有排列的迭代器:
val permutations = List(1, 2, 3, 4, 5, 6, 7).permutations.take(5)
如前所述,这将产生一个包含该特定List的排列的迭代器。由于它很懒,我们只能从序列中取出五个。根据我的理解,这很好,只要我们不在迭代器上调用toString,因为这会导致迭代器计算所有可用数据并将其作为String返回。
虽然懒惰,但这不会解决我的问题。我所追求的是以下内容:
// List of lists
val lists = List(
List(1, 2, 3),
List(3, 2),
List(4, 3, 2, 4))
计算内部List的所有可能排列,同时保持外部List内List的相同排序,外部List中每个List包含的元素数量相同。意思是,内部列表应该以各种可能的方式与其他内部列表一起进行置换,就像它们已被展平一样,同时仍保持相同的顺序并包含与之前相同数量的元素。
因此,一个排列可能会产生:
List(List(1, 3, 2), List(3, 2), List(3, 4, 4, 2))
似乎我不够聪明,无法自己克服这里列出的概念。任何指针,如果不是完整的代码,将非常感谢!如果您有任何问题,请写下评论,我会尽力澄清,或者通过评论或对现有问题进行少量修改。
如果你对这个问题有一个答案,但是用这个问题没有列出的语言,尽可能尝试回答,这主要是我所追求的这种排列的概念!
答案 0 :(得分:1)
如果外部List
的大小已知并且不变,那么可以按如下方式完成。
val ls = List(List(1, 3, 2), List(7, 8), List(9, 4, 4, 5))
val allPerms: Iterator[List[List[Int]]] = for {
a <- ls(0).permutations
b <- ls(1).permutations
c <- ls(2).permutations
} yield List(a,b,c)
在此示例中,生成的Iterator
有144个元素,这是我们应该期望的:6 X 2 X 12 = 144
如果外List
长度是流动的,则任务有点复杂。
<强>更新强>
在这种情况下&#34;更复杂&#34;意味着在提出可能的解决方案之前,我必须对其进行一段时间的研究。
def getAllPerms[A]( in: List[List[A]]
, acc: List[List[A]] = List()
): Iterator[List[List[A]]] = in match {
case end :: Nil => end.permutations.map(acc :+ _)
case hd :: tl => hd.permutations.flatMap(x => getAllPerms(tl, acc :+ x))
case Nil => Iterator() // just to be complete
}
这是递归的,但不是尾递归的。它确实通过了我有限的一组测试。试一试。
答案 1 :(得分:1)
尾递归,懒惰评估解决方案:
@tailrec
def tailRecCombineWith(permutatedLists: Iterator[List[List[Int]]], remainingLists: List[List[Int]]): Iterator[List[List[Int]]] = remainingLists match {
case Nil => permutatedLists
case head :: tail => tailRecCombineWith(for {
a: List[List[Int]] <- permutatedLists
b: List[Int] <- head.permutations
} yield a :+ b, tail)
}
val result: Iterator[List[List[Int]]] =
tailRecCombineWith(lists.head.permutations.map(List(_)), lists.tail)