如何在Scala中获取列表的所有可能分区

时间:2019-03-18 06:50:33

标签: scala list combinations

我有一个字符串列表,例如List("A", "B", "C")。我想在Scala中获取所有可能的分区。我期望的结果是:

def func(List[String]): List[List[String]] = {
// some operations
}
In: func(List("A", "B", "C"))
Out: 
[
[["A"], ["B"], ["C"]], 
[["A", "B"], ["C"]], 
[["A", "C"], ["B"]], 
[["B", "C"], ["A"]], 
[["A", "B", "C"]], 
]

1 个答案:

答案 0 :(得分:0)

这是使用Set的解决方案:

def partitions[T](seq: TraversableOnce[T]): Set[Set[Set[T]]] = {
  def loop(set: Set[T]): Set[Set[Set[T]]] =
    if (set.size < 2) {
      Set(Set(set))
    } else {
      set.subsets.filter(_.nonEmpty).flatMap(sub =>
        loop(set -- sub).map(_ + sub - Set.empty)
      ).toSet
    }

  loop(seq.toSet)
}

使用Set使逻辑更容易,但是如果原始列表中存在重复值,则确实会删除重复值。 List可以使用相同的逻辑,但是您需要实现类似subsets的集合操作。


仅供参考,这是使用List的实现,它将在输入列表中保留重复项。

def partitions[T](list: List[T]): List[List[List[T]]] =
  list match {
    case Nil | _ :: Nil => // 0/1 elements
      List(List(list))
    case head :: tail => // 2+ elements
      partitions(tail).flatMap(part => {
        val joins =
          part.indices.map(i =>
            part.zipWithIndex.map { case (p, j) =>
              if (i == j) {
                head +: p
              } else {
                p
              }
            }
          )

        (List(head) +: part) +: joins
      })
  }