ruby散列中布尔值的排列

时间:2016-01-28 13:46:33

标签: ruby

我需要实现一个函数,它将带有符号的数组作为参数(如[:a :b :c]),然后返回一个数组,其中包含映射到散列中这些符号的布尔值的所有可能排列

[{a: true, b: true, c: true},
{a: false, b: true, c: true},
{a: true, b: false, c: true},
{a: true, b: true, c: false},
{a: true, b: false, c: false},
{a: false, b: false, c: true},
{a: false, b: true, c: false},
{a: false, b: false, c: false}]

在ruby中实现这样的东西的优雅方式是什么?

3 个答案:

答案 0 :(得分:7)

我使用repeated_permutation执行此任务:

[true, false].repeated_permutation(3)
             .map { |a, b, c| { a: a, b: b, c: c } }
#=> [{:a=>true, :b=>true, :c=>true},
#    {:a=>true, :b=>true, :c=>false},
#    {:a=>true, :b=>false, :c=>true},
#    {:a=>true, :b=>false, :c=>false},
#    {:a=>false, :b=>true, :c=>true},
#    {:a=>false, :b=>true, :c=>false},
#    {:a=>false, :b=>false, :c=>true},
#    {:a=>false, :b=>false, :c=>false}]

或使用一系列键:

keys = %i(a b c)
[true, false].repeated_permutation(keys.size)
             .map { |values| keys.zip(values).to_h }

答案 1 :(得分:4)

我们可以利用输出散列中true / false的模式遵循0到(2 ary.size -1)之间的二进制数序列的事实,并且做类似下面的事情

require "pp"

ary = [:a,:b,:c]

result = (0...2**ary.size).map do |num|
  bool_array = (0...ary.size).map do |bit_pos| 
    num[bit_pos].zero?
  end
  ary.zip(bool_array).to_h 
end

pp result
#=> [{:a=>false, :b=>false, :c=>false},
#    {:a=>true, :b=>false, :c=>true},
#    {:a=>false, :b=>true, :c=>true},
#    {:a=>true, :b=>true, :c=>true},
#    {:a=>false, :b=>false, :c=>false},
#    {:a=>true, :b=>false, :c=>true},
#    {:a=>false, :b=>true, :c=>true},
#    {:a=>true, :b=>true, :c=>true}]

答案 2 :(得分:1)

另一种方法是使用递归:

def permute(arr)
  first, *rest = arr
  return [{ first=>:true }, { first=>:false }] if rest.empty? 
  permute(rest).flat_map { |h| [{ first=>:true }.merge(h), { first=>:false }.merge(h)] } 
end

permute([:a, :b, :c])
  #=> [{:a=>:true,   :b=>:true,   :c=>:true }, {:a=>:false, :b=>:true,  :c=>:true },
  #    {:a=>:true,   :b=>:false,  :c=>:true }, {:a=>:false, :b=>:false, :c=>:true },
  #    {:a=>:true,   :b=>:true,   :c=>:false}, {:a=>:false, :b=>:true,  :c=>:false},
  #    {:a=>:true,   :b=>:false,  :c=>:false}, {:a=>:false, :b=>:false, :c=>:false}]