翻译函数,用于查找从Python到Ruby的集合的所有分区

我有以下python函数以递归方式查找集合的所有分区:

def partitions(set_): if not set_: yield [] return for i in xrange(2**len(set_)/2): parts = [set(), set()] for item in set_: parts[i&1].add(item) i >>= 1 for b in partitions(parts[1]): yield [parts[0]]+b for p in partitions(["a", "b", "c", "d"]): print(p) 

有人可以帮我翻译成ruby吗? 这是我到目前为止:

 def partitions(set) if not set yield [] return end (0...2**set.size/2).each { |i| parts = [Set.new, Set.new] set.each { |item| parts[i&1] <>= 1 } partitions(parts[1]).each { |b| yield [parts[0]] << b } } end p partitions([1, 2, 3, 4].to_set) 

我收到错误“LocalJumpError:no block given”。 我想这是因为yield函数在Python和Ruby中的工作方式不同。

 #!/usr/bin/ruby1.8 def partitions(set) yield [] if set.empty? (0 ... 2 ** set.size / 2).each do |i| parts = [[], []] set.each do |item| parts[i & 1] << item i >>= 1 end partitions(parts[1]) do |b| result = [parts[0]] + b result = result.reject do |e| e.empty? end yield result end end end partitions([1, 2, 3, 4]) do |e| pe end # => [[1, 2, 3, 4]] # => [[2, 3, 4], [1]] # => [[1, 3, 4], [2]] # => [[3, 4], [1, 2]] # => [[3, 4], [2], [1]] # => [[1, 2, 4], [3]] # => [[2, 4], [1, 3]] # => [[2, 4], [3], [1]] # => [[1, 4], [2, 3]] # => [[1, 4], [3], [2]] # => [[4], [1, 2, 3]] # => [[4], [2, 3], [1]] # => [[4], [1, 3], [2]] # => [[4], [3], [1, 2]] # => [[4], [3], [2], [1]] 

有什么不同:

  • 守卫叫set.empty? 而不是(隐式)测试set.nil?
  • 在调用分区时省略.each
  • 使用Array而不是Set
  • 从生成的结果中筛选出空集

您必须将Ruby的yield视为对用户定义操作的调用。

 def twice yield yield end twice { puts "Hello" } 

因此,只要您的代码产生一个值,就会调用该元素的处理函数。

 partitions([1, 2, 3, 4].to_set) { |result| # process result } 

此代码根本不生成列表。