HarshaHegde has asked for the wisdom of the Perl Monks concerning the following question:

Revered Monks, How do I intersect two hashes and get a third hash? I searched the forum, but didn't find anything.

Replies are listed 'Best First'.
Re: Intersect two hashes
by Corion (Patriarch) on Jun 10, 2007 at 18:19 UTC

    This is a FAQ. As perlfaq4 is currently down, use the built-in documentation search for Perl:

    perldoc -q intersect

    Update:Aaah - we have a local, outdated copy of the answer. But that answer hasn't changed for a decade, I guess ;)

      Corion,

      The perlfaq describes intersection of two arrays. I feel this is a better solution for intersecting arrays than what is mentioned in the faq.

      However, I am looking to intersect hashes. What I am doing right now is :

      foreach (keys %hash1){ $intersected_hash{$_} = $hash1{$_} if exists $hash2{$_}; }
      Is there a better way to do this?

        I mentioned the FAQ because the only meaningful interpretation of "intersection" of two hashes is the intersection of their keys, which leads back to determining the intersection of two lists. I would code the loop a bit differently:

        my @intersection = grep { exists $hash2{$_} } keys %hash1; my %intersection; @intersection{ @intersection } = @hash1{ @intersection };

        Update: I made an error and had my %intersection where I should have assigned a hash slice instead. Fixed, thanks to ysth!

        Update 2: Fixed a syntax error - you can't declare a hash slice via my. Spotted again by ysth!

        The perlfaq describes intersection of two arrays. I feel this is a better solution for intersecting arrays than what is mentioned in the faq.

        The faq is constantly updated to provide good answers but it is not perfect. More importantly, it gives example code for certain situations, that can be easily adapted to others.

        BTW: the link you inserted brought me to another incarnation of PM: this is annoying. To put it in a way that will be agnostic, just use [id://2461] or [id://2461|this], which will render respectively like How can I find the union/difference/intersection of two arrays? and this respectively.

        However, I am looking to intersect hashes.

        Hashes are functions: their keys can be regarded as sets. Sets have intersections, functions generally not. (But possibly in some particular branch of Mathematics.) Judging from your code and using intechangeably the word "hash" and the word "function", you want the restriction of the first hash to the intersection of its domain with that of the second one. The idiom in Perl for such a restriction is a slice which will work like thus: @hash1{LIST}. (A slice will also do more, but let's set that aside for the moment.) The given LIST can be simply built with grep. Thus:

        my %intersected_hash = @hash1{grep exists $hash2{$_}, keys %hash1};
Re: Intersect two hashes
by ysth (Canon) on Jun 10, 2007 at 21:56 UTC
    Assuming by intersect you mean create a third hash with only those keys that are in both original hashes, what do you want the values of the new hash to be?
Re: Intersect two hashes
by dk (Chaplain) on Jun 11, 2007 at 08:24 UTC
    deleted message - wrote here by mistake, left wondering how I'd delete the comment...