我有一组某种类型的项目,并希望产生它的权力集中。
我在网上搜索,但没有找到那这不会忽略特定任务的任何Scala代码。
这是我想出了。 它可以限制由长度参数所产生的集的基数。
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
}
这将不包括空集。 要做到这一点,你就必须在方法的最后一行改变简单地水库+集()
任何建议如何能在一个更实用的风格来完成?
Answer 1:
注意,如果有一组S
和另一组T
其中T = S ∪ {x}
即T
是S
与一种元素加入),那么的幂T
- P(T)
-可在来表示P(S)
和x
如下:
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))
它实际上看起来更漂亮做着同样的一个List
(即递归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]]
Answer 2:
看起来没有人知道这件事早在7月,但有一个内置的方法: subsets
。
scala> Set(1,2,3).subsets foreach println
Set()
Set(1)
Set(2)
Set(3)
Set(1, 2)
Set(1, 3)
Set(2, 3)
Set(1, 2, 3)
Answer 3:
下面是更有趣的方式来写一个:
import scalaz._, Scalaz._
def powerSet[A](xs: List[A]) = xs filterM (_ => true :: false :: Nil)
其按预期工作:
scala> powerSet(List(1, 2, 3)) foreach println
List(1, 2, 3)
List(1, 2)
List(1, 3)
List(1)
List(2, 3)
List(2)
List(3)
List()
例如,见这个话题了它是如何工作的解释。
(正如在评论debilski笔记, ListW
也皮条客powerset
到List
,但不好玩。)
Answer 4:
使用内置的combinations
功能:
val xs = Seq(1,2,3)
(0 to xs.size) flatMap xs.combinations
// Vector(List(), List(1), List(2), List(3), List(1, 2), List(1, 3), List(2, 3),
// List(1, 2, 3))
请注意,我欺骗和使用的Seq
,因为原因不明, combinations
被定义SeqLike
。 因此,与一组,你需要转换到/从一个Seq
:
val xs = Set(1,2,3)
(0 to xs.size).flatMap(xs.toSeq.combinations).map(_.toSet).toSet
//Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3),
//Set(1, 2))
Answer 5:
所有其他的答案似乎有点复杂,下面是一个简单的函数:
def powerSet (l:List[_]) : List[List[Any]] =
l match {
case Nil => List(List())
case x::xs =>
var a = powerSet(xs)
a.map(n => n:::List(x)):::a
}
所以
powerSet(List('a','b','c'))
会产生以下结果
res0: List[List[Any]] = List(List(c, b, a), List(b, a), List(c, a), List(a), List(c, b), List(b), List(c), List())
Answer 6:
可以简单的:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] =
xs.foldLeft(Seq(Seq[A]())) {(sets, set) => sets ++ sets.map(_ :+ set)}
递归实现:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] = {
def go(xsRemaining: Seq[A], sets: Seq[Seq[A]]): Seq[Seq[A]] = xsRemaining match {
case Nil => sets
case y :: ys => go(ys, sets ++ sets.map(_ :+ y))
}
go(xs, Seq[Seq[A]](Seq[A]()))
}
Answer 7:
这里还有一个(懒惰)版本...因为我们正在收集计算发电机组的方式,我想我会添加它:
def powerset[A](s: Seq[A]) =
Iterator.range(0, 1 << s.length).map(i =>
Iterator.range(0, s.length).withFilter(j =>
(i >> j) % 2 == 1
).map(s)
)
Answer 8:
下面是使用一个辅助函数的简单,递归解决方案:
def concatElemToList[A](a: A, list: List[A]): List[Any] = (a,list) match {
case (x, Nil) => List(List(x))
case (x, ((h:List[_]) :: t)) => (x :: h) :: concatElemToList(x, t)
case (x, (h::t)) => List(x, h) :: concatElemToList(x, t)
}
def powerSetRec[A] (a: List[A]): List[Any] = a match {
case Nil => List()
case (h::t) => powerSetRec(t) ++ concatElemToList(h, powerSetRec (t))
}
这样的呼唤
powerSetRec(List("a", "b", "c"))
会给结果
List(List(c), List(b, c), List(b), List(a, c), List(a, b, c), List(a, b), List(a))
文章来源: How to generate the power set of a set in Scala