2014-01-25 3 views
1

가능한 값 집합과 임의의 값의 해시가 주어진 경우 가능한 모든 가능한 조합에 nil 값을 모두 바꿀 수 있습니까?가능한 모든 값을 사용하여 해시에서 와일드 카드 값 채우기

values = %w[a b c] 
hash = { x:1, y:2, z:nil } 
fill_wildcards(hash, values) 
#=> [{ x:1, y:2, z:'a' }, 
#=> { x:1, y:2, z:'b' }, 
#=> { x:1, y:2, z:'c' }] 

hash = { x:1, y:nil, z:nil } 
fill_wildcards(hash, values) 
#=> [{ x:1, y:'a', z:'a' }, 
#=> { x:1, y:'a', z:'b' }, 
#=> { x:1, y:'a', z:'c' }, 
#=> { x:1, y:'b', z:'a' }, 
#=> { x:1, y:'b', z:'b' }, 
#=> { x:1, y:'b', z:'c' }, 
#=> { x:1, y:'c', z:'a' }, 
#=> { x:1, y:'c', z:'b' }, 
#=> { x:1, y:'c', z:'c' }] 

I 교체해야 할 키를 찾을 수 있습니다 :

예를 들어

wildkeys = hash.select{ |k,v| v.nil? }.map(&:first) 
#=> [:y, :z] 

를 그리고 이렇게 나는 할 수 find all the permutations of values needed :

wildvalues = values.repeated_permutation(wildkeys.length).to_a 
#=> [["a", "a"], ["a", "b"], ["a", "c"], ["b", "a"], 
#=> ["b", "b"], ["b", "c"], ["c", "a"], ["c", "b"], ["c", "c"]] 

하지만 간단한 방법을 생각할 수 없다. 이 두 개를 원본으로 병합합니다.

답변

2

는 다음과 같이 될 수 있습니다

rest = hash.reject { |k,v| v.nil? }.to_a 
wildvalues.map { |wv| Hash[rest + wildkeys.zip(wv)] } 

또는

wildvalues.map { |wv| hash.merge(Hash[wildkeys.zip(wv)]) } 
+0

. 감사. – Phrogz

2
def fill_wildcards(hsh, values) 
    values.repeated_permutation(hsh.values.count(nil)).to_a.map {|combo| hsh.each_with_object(hsh.dup) {|(k,v),hsh| hsh[k] = combo.shift unless v } } 
end 
1

또 다른 방법 :

코드

def doit(hash, values) 
    a = hash.map { |k,v| [k].product(v ? [v] : values) } 
    a.shift.product(*a).map(&:to_h) 
end 
마지막 완벽하는지

데모

values = %w[a b c] 

hash = { x:1, y:2, z:nil } 
p doit(hash, values) 
    #=> [{:x=>1, :y=>2, :z=>"a"}, 
    # {:x=>1, :y=>2, :z=>"b"}, 
    # {:x=>1, :y=>2, :z=>"c"}] 

hash = { x:1, y:nil, z:nil } 
p doit(hash, values) 
    #=> [{:x=>1, :y=>"a", :z=>"a"}, 
    # {:x=>1, :y=>"a", :z=>"b"}, 
    # {:x=>1, :y=>"a", :z=>"c"}, 
    # {:x=>1, :y=>"b", :z=>"a"}, 
    # {:x=>1, :y=>"b", :z=>"b"}, 
    # {:x=>1, :y=>"b", :z=>"c"}, 
    # {:x=>1, :y=>"c", :z=>"a"}, 
    # {:x=>1, :y=>"c", :z=>"b"}, 
    # {:x=>1, :y=>"c", :z=>"c"}] 

    hash = { x:nil, y:nil, z:nil } 
    p doit(hash, values).size #=> 27