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

I am creating the Values array from a file and i have the ID in values[0] I am checking if that ID is exists in the Hash that I created. if it's exists I copy the Values2 to my AOH. The Code is working fine. But I have a proplem that if I have ID that occured twice or more, it would only print for one of them. I would like change my code, so that it can also copy the ID for the other even if i have more the one.

Here is my current output: <td <td <td <td <td <td
60811
50813
820
34820
821
32821
I would like to see: <td <td <td <td <td <td
60811
50813
34820
34820
32821
32821

@values = split /\s*,\s*/, $line;
if ( $intcounter > 0 )
{
 if ( exists( $Hash{ $values[0] } ) ) 
 {
   $intrec = $Hash{ $values[0] };					
   $AoH[$intrec]{'Data'} = $values[1];
 }
 else
 {
  #print "ID can't be found in the data file\n";
 }
}
$intcounter++

Replies are listed 'Best First'.
Re: ID exists in Hash -I need to copy the value even if it exists more than one
by Laurent_R (Canon) on Mar 01, 2014 at 11:05 UTC
    You cannot have duplicate keys with a hash. Besides the hard-coded 'data' hash key does not seem to make much sense, and I am not convinced that the data structure you are using is the best one, but it may be because you showed only a small part of your code. If you really need an array of hashes, then you should probably change it to an array of hashes of arrays, or you could possibly use an array of arrays. An example of one possibility under the Perl debugger:
    DB<4> @values = qw / 60 811/; DB<5> push @{$AoA[$values[0]]}, $values[1]; DB<6> @values = qw / 60 812/; DB<7> push @{$AoA[$values[0]]}, $values[1]; DB<8> x \@AoA 0 ARRAY(0x80430518) 0 empty slot 1 empty slot 2 empty slot 3 empty slot (...) 58 empty slot 59 empty slot 60 ARRAY(0x803f50f0) 0 811 1 812
    This shows, however, that using an array as the first level of the data structure is probably not the best idea: these 60 empty slots are a waste of memory. A HoA might be better:
    DB<1> ($key,$val) = qw / 60 811/; DB<2> push @{$HoA{$key}}, $val; DB<3> ($key,$val) = qw / 60 812/; DB<4> push @{$HoA{$key}}, $val; DB<5> x \%HoA 0 HASH(0x80359cb0) 60 => ARRAY(0x8035ffa8) 0 811 1 812 DB<6> print "@{$HoA{60}}" 811 812
Re: ID exists in Hash -I need to copy the value even if it exists more than one
by kcott (Archbishop) on Mar 01, 2014 at 20:34 UTC

    G'day MSOL,

    Welcome to the monastery.

    You appear to have messed up your HTML table markup (i.e. "<td  <td  <td  <td  <td  <td"); however, from your initial description, I'll assume the data (as seen) is OK: please advise if this is a wrong assumption.

    Sample input would have been useful: I've created dummy data (in the code below) based on your posted code. Again, please advise if my guess at this is wrong.

    I also don't know how the output should be ordered. What you've shown appears grouped by key but otherwise haphazard.

    To retain the order of keys as first seen in the input, this technique should suffice:

    #!/usr/bin/env perl -l use strict; use warnings; my (%data, @order); while (<DATA>) { chomp; my ($key, $value) = split /\s*,\s*/; push @order, $key unless exists $data{$key}; push @{$data{$key}}, $value; } for my $key (@order) { print "|$key|$_|" for @{$data{$key}}; } __DATA__ 60,811 50, 813 34 , 820 32,821 34 ,820 32 , 821

    Output:

    |60|811| |50|813| |34|820| |34|820| |32|821| |32|821|

    If you don't care about order (but still want to group the keys), you can just do this:

    #!/usr/bin/env perl -l use strict; use warnings; my %data; while (<DATA>) { chomp; my ($key, $value) = split /\s*,\s*/; push @{$data{$key}}, $value; } for my $key (keys %data) { print "|$key|$_|" for @{$data{$key}}; } __DATA__ 60,811 50, 813 34 , 820 32,821 34 ,820 32 , 821

    Hash keys aren't ordered so your output may well differ from mine; you may even get a different order each time you run the code. Here's the output from a sample run:

    |34|820| |34|820| |60|811| |32|821| |32|821| |50|813|

    -- Ken

      Thanks Ken. That was helpful

Re: ID exists in Hash -I need to copy the value even if it exists more than one
by Anonymous Monk on Mar 01, 2014 at 09:21 UTC