in reply to Re: Need advice on checking two hashes values and keys
in thread Need advice on checking two hashes values and keys

I appreciate all the advice and examples to manipulate hash, hash table, code improvement and will do all of these with your help.

should I create a new thread for each example or stick with this thread? maybe some other newbie can learn from it.

Ok, I've been playing with hash ref to get a 2 element hash.

hasn't worked yet. will you provide some instruction/teach/explain the error I did on hash ref? error it gave me.

Can't use string ("dos") as an ARRAY ref while "strict refs" in use at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essentials\hash_ref_6_4.pl line 34, <$in1> line 1.

use strict; use warnings; use Data::Dump qw(dump); my %hash; #my file handles UNTIL I figure how to install the Inline::File module + to netbeans IDE open my $in, '<',"./test_data.txt" or die ("can't open the file:$!\n") +; open my $in1,'<',"./test_data1.txt" or die ("can't open file : $!\n"); open my $out ,'>' ,"./test_data_out.txt" or die "can't open the file f +or write:$!\n"; open my $out1 ,'>',"./test_data_out1_no_match.txt" or die "can't open +file for write:$!\n"; #creating hash while (<$in>){ chomp; my ($key,$value)= split(/\s*=\s*/); #conto di spazio prima o dopo +la parola $hash{$key}=$value; } close $in; #using the first hash while (<$in1>){ chomp; my($key,$value)=split/\s*=\s*/ ; #push the value to existing hash as to get reference if key exists # %hash =( It => [Spa Fre]) #using one hash as per Ken code suggestion?? push @{$hash{$key}},$value if $hash{$key}; #non so come funzio +na "push" print $out dump (\%hash); } close $in1; close $out; close $out1;

Replies are listed 'Best First'.
Re^3: Need advice on checking two hashes values and keys
by aaron_baugher (Curate) on Jun 04, 2015 at 21:54 UTC

    (I'd suggest that you keep posting to this thread as long as you're working on the same problem, unless people stop responding to it.)

    Ok, let's say you want to create a hash of two-element arrays, with the hash keys being the Italian numbers, each one pointing to a reference to a two-element array holding the Spanish and French numbers, in that order. Then as you're going through the first loop (Italian = Spanish), you need to insert the Spanish numbers as the first element of an array rather than a simple value:

    $hash{$italian} = [ $spanish ];

    The square brackets return a reference to an array, which is a scalar that can be stored as a value in the hash. So now it looks like this, with references to one-element arrays as the values:

    $hash = ( uno => [ 'uno' ], due => [ 'dos' ], # and so on );

    Then in the second loop, you need to add the French numbers to the arrays corresponding to their matching Italian hash keys. There are two ways you could do this:

    # by assigning directly to the second element of the sub-array $hash{$italian}[1] = $french; # or by dereferencing the sub-array pointed to by the hash value # and pushing the new value onto the end of that array push @{$hash{$italian}}, $french; # Either way, you'll end up with: $hash = ( uno => [ 'uno','un' ], due => [ 'dos','deux' ], # and so on );

    Then when you're ready to print them out, you loop through the keys of the hash, printing the key and the elements of the sub-array as you wish:

    for my $key (keys %hash){ print $key, ' => ', join ' , ', @{$hash{$key}}; # dereference sub-ar +ray print "\n"; }

    The trick is keeping track of what level of the structure you're dealing with, and getting the sigils (and arrows, if necessary) right for pointing to the right things, whether values or references.

    Aaron B.
    Available for small or large Perl jobs and *nix system administration; see my home node.

      cool. the square brackets was the correct method to do a ref to array...missed it although I read about it last night.thanks.

      several questions

      PROBLEM: the array seem to list of all of the numbers found in both files. I want to only print out the numbers that are fund on BOTH in one file then the numeri not found in the other into another file

      my IF check doesn't seem to work?

      push @{$hash{$key}},$value if $hash{$key}; #non so come funziona "push"

      how is this piece of code work? I don't understand the "[1]", I think +it's a matrix , is it placement spot??
      $hash{$italian}[1] = $french;

        Okay, if there could be numbers in one file but not the other (I forgot about that in your original data), you won't be able to use the push method, because numbers that weren't in the Spanish file will end up getting the French word in the Spanish spot. So you'll need to do it this way:

        $hash{$italian}[1] = $french;

        What that does is looks up the array pointed to by the reference in $hash{$italian}, and sets the second element of the array to the value in $french. The cool part is that $hash{$italian} doesn't even have to exist yet; it will be created automatically if it doesn't (that's called autovivification). So numbers that are only in the Spanish file will only have the first element of the array set, and numbers only in the French file will only have the second element set (the first element will be undef). So you'll end up with something like this (I made my own smaller input files to show what I mean):

        # Italian -> Spanish input file with 1 & 3 uno = uno tre = tres # Italian -> French input file with 2 & 3 due = deux tre = trois # the hash will be: $hash = ( uno => [ 'uno' ], due => [ undef, 'deux' ], tre => [ 'tres','trois' ], );

        See how the missing Spanish word for 2 is undefined, since we inserted the French word into the second element of the array? Now to print them out, you can check each array to see if both elements are present, and print to one file if they are, and the other file if they aren't:

        for my $key (keys %hash){ if( $hash{$key}[0] and $hash{$key}[1] ){ # both are present print $out "$key => ", join( ' , ', @{$hash{$key}}), "\n"; } else { # one is missing print $out1 "$key => ", join( ' , ', @{$hash{$key}}), "\n"; } }

        Now, in the else portion, you'll get a warning when it prints out an undefined value. You can ignore that, since you're expecting it, or turn off warnings in that section, or deal with it by putting in some "print if it exists" logic. That's up to you, and depends somewhat on what you want that second file to tell you about what's missing.

        Aaron B.
        Available for small or large Perl jobs and *nix system administration; see my home node.