Skip to content

Instantly share code, notes, and snippets.

@georgkreimer
Created November 19, 2010 14:07
Show Gist options
  • Save georgkreimer/706551 to your computer and use it in GitHub Desktop.
Save georgkreimer/706551 to your computer and use it in GitHub Desktop.
Hash intersection in Ruby
first = {"a" => 4, "b" => 1, "c" => 3, "g" => 201, "h" => 501}
second = {"d" => 19, "e" => 18, "c" => 17, "g" => 201, "h" => 501}
keys_intersection = first.keys & second.keys
merged = first.dup.update(second)
intersection = {}
keys_intersection.each do |k|
intersection[k]=merged[k] unless first[k] != second[k]
end
# same thing as freedom patch
class Hash
def intersection(another_hash)
keys_intersection = self.keys & another_hash.keys
merged = self.dup.update(another_hash)
intersection = {}
keys_intersection.each {|k| intersection[k] = merged [k] unless self[k] != another_hash[k]}
intersection
end
end
{"a" => 4, "b" => 1, "c" => 3, "g" => 201, "h" => 501}.intersection({"d" => 19, "e" => 18, "c" => 17, "g" => 201, "h" => 501})
=> {"g"=>201, "h"=>501}
@marxarelli
Copy link

You'd want to use reject instead of delete_if to be nondestructive. And I'd personally prefer to implement it as & to match Array.

class Hash
  def &(other)
    reject { |k, v| !(other.include?(k) && other[k] == v) }
  end
end

The use of include? is necessary to avoid inclusion of surprise nil values in the result.

irb(main):006:0> {:x => 1, :y => 2, :z => nil} & {:y => 2}
=> {:y=>2}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment