我需要实现一个函数,它将带有符号的数组作为参数(如[: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中实现这样的东西的优雅方式是什么?
答案 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}]