生成集合的powerset,而不在Erlang或Ruby中保留堆栈

生成集合的powerset,而不在Erlang或Ruby中保留堆栈,ruby,erlang,subset,powerset,Ruby,Erlang,Subset,Powerset,我想生成一个相当大的集(大约30-50个元素)的功率集,我知道存储功率集需要2^n 是否可以一次生成一个子集 即,通过迭代生成集合的功率集,将生成的每个子集保存到磁盘/数据库,将其从堆栈/内存中删除,然后继续生成其他子集 不幸的是,我未能根据自己的需要修改和示例。生成列表的幂集(实际上就是您的Erlang示例使用的幂集)的一种方法是迭代从0到2^n(独占)的所有数字x,并针对每个x,当且仅当设置了x的ith位时,生成包含原始列表的ith元素的列表 由于使用此方法生成当前列表只取决于x的值,而不取

我想生成一个相当大的集(大约30-50个元素)的功率集,我知道存储功率集需要
2^n

是否可以一次生成一个子集

即,通过迭代生成集合的功率集,将生成的每个子集保存到磁盘/数据库,将其从堆栈/内存中删除,然后继续生成其他子集


不幸的是,我未能根据自己的需要修改和示例。

生成列表的幂集(实际上就是您的Erlang示例使用的幂集)的一种方法是迭代从0到2^n(独占)的所有数字
x
,并针对每个
x
,当且仅当设置了
x
i
th位时,生成包含原始列表的
i
th元素的列表

由于使用此方法生成当前列表只取决于
x
的值,而不取决于以前生成的任何列表,因此使用后不必将列表保存在内存中。因此,这种方法可以用来做你想做的事情。

这使用了标准的“位数组”技巧来生成发电机组(并且它使用了Ruby的
整数
表现为位数组的事实)。但更重要的是,它使用
枚举器
惰性地生成集合

require 'set'

module Enumerable
  def powerset
    number_of_sets = 2 ** count

    Enumerator.new {|ps|
      number_of_sets.times {|i|
        ps << Set[*reject.with_index {|_, j| i[j].zero? }]
      }
    }
  end
end

编辑:如果没有给出块,则添加枚举数(如@Jörg W Mittag)

class Array
  def powerset
    return to_enum(:powerset) unless block_given?
    1.upto(self.size) do |n|
      self.combination(n).each{|i| yield i}
    end
  end
end
# demo
['a', 'b', 'c'].powerset{|item| p item} # items are generated one at a time
ps = [1, 2, 3, 4].powerset # no block, so you'll get an enumerator 
10.times.map{ ps.next } # 10.times without a block is also an enumerator
输出

["a"]
["b"]
["c"]
["a", "b"]
["a", "c"]
["b", "c"]
["a", "b", "c"]
[[1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

require'set'
不再需要了。当然,你是对的。如果你想生成一个实际的幂集,而不是“幂数组”,你需要先将这些组合转换成幂集,然后再将它们交给枚举器。我知道如何在Erlang中从2^n开始迭代所有数字x,但我不了解条件(我不擅长位运算)。您能提供一个简单的例子吗?@Martin:条件是
I波段(1 bsl位置)=/=0
(取自您链接的Erlang代码)。实际上,您可以从链接的代码中获取整个内部列表,即
[lists:nth(Pos+1,Lst)| | Pos
class Array
  def powerset
    return to_enum(:powerset) unless block_given?
    1.upto(self.size) do |n|
      self.combination(n).each{|i| yield i}
    end
  end
end
# demo
['a', 'b', 'c'].powerset{|item| p item} # items are generated one at a time
ps = [1, 2, 3, 4].powerset # no block, so you'll get an enumerator 
10.times.map{ ps.next } # 10.times without a block is also an enumerator
["a"]
["b"]
["c"]
["a", "b"]
["a", "c"]
["b", "c"]
["a", "b", "c"]
[[1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]