2016-01-28 41 views
1

我需要實現一個函數,它得到一個陣列使用符號作爲參數等[:a :b :c],然後,返回其包含在哈希映射到這些符號布爾值的所有可能的排列一個陣列排列組合的布爾值的

like

[{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中實現這樣的事情的優雅方式?

回答

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

順便說一句:'Integer'對象'[]響應'在二進制補碼錶示該索引處的比特的值。 –

+0

@JörgWMittag非常感謝您的意見。有更新使用'[]'。 –

+1

您可以使用num [bit_pos] .zero?'來避免'[true,false]'數組' – Stefan

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