Oktav
Oktav

Reputation: 2151

How do I intersect one hash's keys with another and filter out the matching values?

I got this from the Rails doc:

{1 => 2}.diff(1 => 2)         # => {}
{1 => 2}.diff(1 => 3)         # => {1 => 2}
{}.diff(1 => 2)               # => {1 => 2}
{1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}

This is almost perfect but I don't want values that are in the hash passed as parameter and not in the calling hash.

What I want:

{}.diff(1 => 2) # => {}
{a: 1}.diff({a: 1, b: 2}) # => {} instead of {:b => 2}

Also, it must be as efficient as possible. For instance, I don't want to go over the second hash and check that each key that's inside doesn't appear in the first.

Any ideas?

Upvotes: 0

Views: 83

Answers (2)

Chris Heald
Chris Heald

Reputation: 62668

This is pretty easy:

a.select {|k, v| b.key?(k) && b[k] != v }

This is O(n), since both key? and Hash#[] are both O(1).

Upvotes: 1

aceofspades
aceofspades

Reputation: 7586

Looking at the source is helpful here.

def diff(h2)
  dup.delete_if { |k, v| h2[k] == v }.merge!(h2.dup.delete_if { |k, v| has_key?(k) })
end

Which iterates over every entry in the hash. I'm assuming you don't want to add an unnecessary iteration. So it's easier than the above

def my_diff(h2)
  dup.delete_if { |k, v| h2[k] == v }
end

Upvotes: 2

Related Questions