Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Scala中生成集合的幂集_Scala_Set_Powerset - Fatal编程技术网

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

如何在Scala中生成集合的幂集,scala,set,powerset,Scala,Set,Powerset,我有一组某种类型的项目,并希望生成其电源集 我在网上搜索,找不到任何处理这个特定任务的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 + _)

我有一组某种类型的项目,并希望生成其电源集

我在网上搜索,找不到任何处理这个特定任务的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
   }
def power[T](设置:设置[T],长度:Int)={
var res=Set[Set[T]]()
res++=set.map(set(+uu))
对于(i set.map(x+)。展平
物件
}
这将不包括空集。要实现这一点,您必须将方法的最后一行简单地更改为res+Set()


有没有关于如何以更实用的方式实现这一点的建议?

请注意,如果您有一组
S
和另一组
T
,其中
T=S∪ {x} 
(即
T
S
,添加了一个元素),那么
T
-
P(T)
-的功率集可以用
P(S)
x
表示如下:

P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }
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]]
也就是说,您可以递归地定义功率集(请注意,这将免费为您提供功率集的大小,即添加1个元素将使功率集的大小加倍)。因此,您可以在scala中递归地执行此尾部操作,如下所示:

P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }
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]]
然后:

使用
列表
(即递归ADT)执行相同操作实际上看起来更好:


使用内置的
组合
功能:

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))
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))
}
    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
      }
注意,我作弊并使用了
Seq
,因为原因不明,
组合
是在
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))

以下是一种更有趣的写作方式:

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
上,但这并不有趣。)

看起来在7月份没有人知道,但有一个内置方法:
子集

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)
这是另一个(懒惰的)版本。。。由于我们正在收集计算功率集的方法,我想我应该添加它:

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)
  )
def动力装置[A](序列[A])= 迭代器范围(0,1 迭代器.range(0,s.length).withFilter(j=> (i>>j)%2==1 ).地图(s) ) 可以简单到:

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]()))
}

下面是一个使用辅助函数的简单递归解决方案:

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))
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))
}
    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
      }
所以

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))

所有其他答案似乎都有点复杂,下面是一个简单的函数:

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))
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))
}
    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
      }
所以

将产生以下结果

    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())

我喜欢这样-我的问题是,
filterM
还有什么用途?@oxbow\u例如,你可以做一个三向谓词过滤器。(
x=>if…
None
/
Some(false)
/
Some(true)
)。单个
None
将清除整个输入。但是我想我从未听说过的奇异单子会有更高级的用法。它是内置的:
List(1,2,3)。powerset
:)@oxbow_lakes:
let doYouLike it=fmap(=“y”)$putStr(“你喜欢”++展示它++“(y/n)?”>>过滤器中的getLine doYouLike[“scala”,“haskell”]
filterM
和朋友对
M=[a]状态[X,a]
非常有用。例如,您可以使用以下内容过滤掉重复:虽然这段代码可以回答这个问题,但最好包含一些上下文,解释它是如何工作的以及何时使用它。从长远来看,只有代码的答案是没有用的。福德勒夫特的功劳。我一直在寻找具体的实现。正如一位早期的评论者所说,一个解释会很好。结果中缺少空集,但是使用set,它是否保持字典集?