scala - 如何在Scala中生成集合的幂集

标签 scala set powerset

我有一些类型的项目集,想要生成其功率集。

我在网上搜索,找不到适合此特定任务的任何Scala代码。

这就是我想出的。它允许您限制length参数产生的集合的基数。

def power[T](set: Set[T], length: Int) = {
   var res = Set[Set[T]]()
   res ++= set.map(Set(_))

   for (i <- 1 until length)
      res = res.map(x => set.map(x + _)).flatten

   res
   }

这将不包括空集。为此,您只需将方法的最后一行更改为res + Set()

有什么建议可以以更实用的方式实现吗?

最佳答案

请注意,如果您有一个S设置和另一个T设置(其中T = S ∪ {x}T并添加了一个元素),则S的幂集-T-可以用P(T)P(S)表示,如下所示:

P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }

也就是说,您可以递归定义功率集(请注意,这是如何免费为您提供功率集大小的-即添加1元素会使功率集大小增加一倍)。因此,您可以按以下步骤在scala中以递归方式执行此操作:
scala> def power[A](t: Set[A]): Set[Set[A]] = {
   |     @annotation.tailrec 
   |     def pwr(t: Set[A], ps: Set[Set[A]]): Set[Set[A]] =
   |       if (t.isEmpty) ps
   |       else pwr(t.tail, ps ++ (ps map (_ + t.head)))
   |
   |     pwr(t, Set(Set.empty[A])) //Powerset of ∅ is {∅}
   |   }
power: [A](t: Set[A])Set[Set[A]]

然后:
scala> power(Set(1, 2, 3))
res2: Set[Set[Int]] = Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3), Set(1, 2))

实际上,使用x(即递归ADT)执行此操作看起来要好得多:
scala> def power[A](s: List[A]): List[List[A]] = {
   |     @annotation.tailrec 
   |     def pwr(s: List[A], acc: List[List[A]]): List[List[A]] = s match {
   |       case Nil     => acc 
   |       case a :: as => pwr(as, acc ::: (acc map (a :: _)))
   |     }
   |     pwr(s, Nil :: Nil)
   |   }
power: [A](s: List[A])List[List[A]]

关于scala - 如何在Scala中生成集合的幂集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11581175/

相关文章:

scala - "too generic"类型系统是什么意思?

.net - .NET 2.0 中有集合类型吗?

c++ - 如何将unordered_set与自定义结构一起使用?

erlang - 在 Erlang 中生成没有堆栈的幂集

c++ - 按字典顺序打印给定字符串的所有字母组合的算法

scala - sbt & Play 2.0 调试信息丢失

scala - 无法将环境变量传递给 intellij 中的 sbt 任务

scala - 如何实现多个Silhouette Authenticator?

c# - 错误 CS0051(不一致的可访问性 : parameter type 'Job' is less accessible than method 'AddJobs.TotalPay(Job)' )

ruby - 无需在 Erlang 或 Ruby 中保留堆栈即可生成集合的幂集