Search code examples
rubyboolean-operations

What is the Ruby idiomatic way to merge two hashes of boolean values over boolean operations?


Here is the goal:

a={a:true, b:true, c:true, d:false, e:false, g:false, h:nil,  i:nil, j:nil}
b={a:true, b:false, c:nil, d:true,  e:false, g:nil,   h:true, i:false, j:nil}
c={a:true, b:false, c:nil, d:false, e:false, g:nil,   h:nil,  i:nil, j:nil}
conjonctive_map(a, b) == c # expect to be true

So the question is, what is the idiomatic way to achieve that in Ruby? It doesn't have to be a a conjonctive_map defined method, an inline .map or something like that. Also having any operation implicating nil to return false would also be fine in my case, I proposed a c that allways end up with nil.


Solution

  • a={a:true, b:true, c:true, d:false, e:false, g:false, h:nil,  i:nil, j:nil}
    b={a:true, b:false, c:nil, d:true,  e:false, g:nil,   h:true, i:false, j:nil}
    a.merge(b) { |_, v1, v2| v1 && v2 }
    #⇒ {:a=>true, :b=>false, :c=>nil, :d=>false,
    #   :e=>false, :g=>false, :h=>nil, :i=>nil, :j=>nil}
    

    If for some reason you want nil to prevail over false, this is to be done explicitly:

    c={a:true, b:false, c:nil, d:false, e:false, g:nil,   h:nil,  i:nil, j:nil}
    a.merge(b) { |_, v1, v2| [v1, v2].any?(&:nil?) ? nil : v1 && v2 }
    _ == c
    #⇒ true