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

Hi Perl Monks, I have the below two hash of array of hashes.I need to compare these two array of hashes,each and every field needs to be compared.I cant use diff, I need to do it without using any inbuilt functions. Please help me out with this as I am really new to Perl. Thanks a lot in advance. HASH OF ARRAY OF HASHES 1:
{ 'details' => [ { 'name' => 'bbbb', 'time' => 1234, 'place' => AB }, { 'name' => 'aaaa', 'time' => 5678, 'place' => CD }, { 'name' => 'aaaa', 'time' => '91011', 'place' => EF }, { 'name' => 'aaaa', 'time' => '121314', 'place' => GH }, { 'time' => '151617', 'name' => 'cccc', 'place' => IJ }, ] };
HASH OF ARRAY OF HASHES 2:
{ 'details' => [ { 'name' => 'dddd', 'time' => 1234, 'place' => AB }, { 'name' => 'eeee', 'time' => 5678, 'place' => CD }, { 'name' => 'eeee', 'time' => '91011', 'place' => EF }, { 'name' => 'eeee', 'time' => '121314', 'place' => GH }, { 'time' => '151617', 'name' => 'cccc', 'place' => IJ }, ] };

Replies are listed 'Best First'.
Re: Compare array of hashes
by perldigious (Priest) on Aug 25, 2016 at 13:00 UTC

    Hi AnishaM,

    As far as homework questions go, it's really best to figure out a solution to such problems yourself. It's likely your teacher has provided you with the necessary tools to do so if you are being asked to solve this problem. The point is for you to learn the material, and that doesn't happen very well if someone else just hands you the code to do what's asked.

    That said, if you have been trying to solve this problem for an overly long time and are really stuck, show us what you have tried (your code with explanations of how you think it's working) and we might give you some little hints to help you along your way.

    I love it when things get difficult; after all, difficult pays the mortgage. - Dr. Keith Whites
    I hate it when things get difficult, so I'll just sell my house and rent cheap instead. - perldigious
Re: Compare array of hashes
by Marshall (Canon) on Aug 25, 2016 at 18:17 UTC
    "He asked me to do it by iterating through both the structures and then comparing them."

    I would recommend that you start by writing code that just prints these 2 structures.That is the iterating part.

    There are modules like Data::Dumper than can do this for you. But, you should know how to access each individual element for yourself. Once you've done that (can access and print all the pieces), then you can come up with a strategy to compare these various pieces together.

    There are many people here who can easily solve this problem, but we really aren't helping you learn Perl if we give you a "cut-and-paste" thing. Have a "go at it" yourself and post your code. You will get hints if you are "stuck".

      foreach my $arrayItem1(@{$$HOAOH1{details}}) { foreach my $arrayItem2(@{$$HOAOH2{details}}) { foreach my $keyArrayItem1(sort keys%$arrayItem1) { if ($$arrayItem1{$keyArrayItem1} eq $$arrayItem2{$keyArray +Item1}) { print "Match:$$arrayItem1{$keyArrayItem1} $$arrayItem2 +{$keyArrayItem1}\n"; } } } }
      I tried this but it compares each key of every Hash in structure1 with each key of every Hash in structure2.

        ++AnishaM: Good progress. From reading your original question, the results you show are what I thought you wanted. Given that you don't seem happy with those results, here are further ideas

        but it compares each key of every Hash in structure1 with each key of every Hash in structure2

        friendly pedant mode: Technically, for every row (subhash) of the first array and for every row (subhash) of the second array, you are comparing the value of each key in the first subhash to the value of the same key of the second subhash, for a total of 5*5*3=75 comparisons. If you were really comparing the value of every key of each subhash (ie, comparing name to 'name', 'time', and 'place', etc), it would be 5*5*3*3=225 comparisons.

        If you really only want to compare the first row of HOAOH1 with the first row of HOAOH2, the second row with the second row, etc (for a total of 5 outer comparisons and 3 key comparisons = 25), here's a hint: since you want the row# to match for each subhash that's compared, you might want to collapse the arrayItem1 and arrayItem2 loops into a single loop that gives an index, and then use that index to find the appropriate row from each HOAOH#

        I would also recommend printing something during the FALSE condition of your compare, as well, so that you can see better what's going on and how many loops are being executed. You might want to add the outer loop variables to your print statements (whether they be references, indexes, or what have you), so that way you can tell exactly which pairs are being compared.


        update 1: reword the pedant-mode to be more pedantically correct (100% correctness not guaranteed). :-)

        update 2: fix brackets to parenthesis in update 1

        Congratulations AnishaM++. You current code represents a huge leap forward in understanding!

        A few nits, @{$$HOAOH1{details}}... Usually the de-referencing operator "->" would be preferred over the double "$$". This code means exactly the same thing and many would find this easier to read:

        foreach my $arrayItem1(@{$HOAOH1->{details}}) { foreach my $arrayItem2(@{$HOAOH2->{details}}) { foreach my $keyArrayItem1(sort keys %$arrayItem1) { if ($arrayItem1->{$keyArrayItem1} eq $arrayItem2->{$keyArr +ayItem1}) { print "Match:$arrayItem1->{$keyArrayItem1} $arrayItem2 +->{$keyArrayItem1}\n"; } } } } __END__ Match:AB AB Match:1234 1234 Match:CD CD Match:5678 5678 Match:EF EF Match:91011 91011 Match:GH GH Match:121314 121314 Match:cccc cccc Match:IJ IJ Match:151617 151617
        I also had to add quotes around 'AB", 'IJ', etc. in order to make "strict" happy. An assignment that doesn't compile under strict is unusual. use strict; use warnings; will save you a lot of grief in the future. I highly recommend that.

        The code contains a mixture of tabs and spaces. I think as you write more code, you will find that spaces only are the way to go. My tab isn't the same as your tab, etc. Editors designed for writing programs will have a setting "convert tabs to spaces". That makes everything clear and the extra bytes for the spaces vs a tab is meaningless.

        Looking at the output, it is hard for me to figure out what records are involved when something matches/doesn't match. pryrt has some suggestions in that regard. I'd re-read the text of the assignment closely to see if there is some clue about what the instructor wants in terms of output format.

Re: Compare array of hashes
by GotToBTru (Prior) on Aug 25, 2016 at 12:23 UTC

    How did your teacher say to do it?

    But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

      He asked me to do it by iterating through both the structures and then comparing them.

        Check out Not Exactly a Hash Tutorial in the Tutorials section for some ideas. Iterating through hashes is covered, among other very useful topics. If you want to program effectively in Perl, you need to know hashes.

        But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)

        So, that would probably be a good idea. And I'll bet that your lectures or the parts of the book you're supposed to have read and learned from offers answers to your 'gimmé.'

        We're here to help you learn. Doing your homework does not help you learn. So go back to the book and your notes and try to solve your problem. We're here to help if you get stuck on some part of the code you'll bring back (you will bring code back, right?).


        Yet another gimmé request!
        Sorry, we expect SOPW to seek wisdom, not to ask us to do so for them.

Re: Compare array of hashes
by perldigious (Priest) on Aug 26, 2016 at 14:27 UTC

    Hi AnishaM,

    We are really trying to help you help yourself. Marshall provided a good suggestion for making sure your data is what you think it is. Take a look at the following code for examples of inspecting your complex data structure. It really does help to clean up your code, indent properly, and be consistent. I have changed your original data slightly by making all the numbers be numbers instead of a mix of strings and numbers, and all the strings be not barewords. Note the usage of use strict; and use warnings; at the top.

    use strict; use warnings; use Data::Dumper; my %HOAOH1 = ( 'details' => [ { 'name' => 'bbbb', 'time' => 1234, 'place' => 'AB' }, { 'name' => 'aaaa', 'time' => 5678, 'place' => 'CD' }, { 'name' => 'aaaa', 'time' => 91011, 'place' => 'EF' }, { 'name' => 'aaaa', 'time' => 121314, 'place' => 'GH' }, { 'name' => 'cccc', 'time' => 151617, 'place' => 'IJ' }, ] ); print Dumper \%HOAOH1; # See how useful Data::Dumper is for debugging +hashes and more complex data structures? print $HOAOH1{'details'}; # Do you see why this just prints an array r +eference? print "\n"; print @{$HOAOH1{'details'}}; # Do you see why this just prints a bunch + of hash references? print "\n"; foreach my $hash_reference (@{$HOAOH1{'details'}}) # Do you see how th +is loop is accesing the lowest level hash keys and values? { # Do you see the two different ways of de-referencing used here? print "$_=$$hash_reference{$_} " foreach (sort keys %{$hash_refere +nce}); print "\n"; }

    You could also look at the following for help learning as well:

    http://perldoc.perl.org/perldsc.html#Declaration-of-a-HASH-OF-COMPLEX-RECORDS

    http://docstore.mik.ua/orelly/perl4/prog/ch09_03.htm

    I love it when things get difficult; after all, difficult pays the mortgage. - Dr. Keith Whites
    I hate it when things get difficult, so I'll just sell my house and rent cheap instead. - perldigious