in reply to specific array in hash of arrays

Another thing that's got me confused is why this returns nothing.
#!/usr/bin/perl use strict; my %hoa = ( "arraya" => [ "dd1", "dd2", "dd3", "dd4" ], "arrayb" => [ "gg1", "gg2", "gg3", "gg4" ], "arrayc" => [ "cc1", "cc2", "cc3", "cc4" ] ); my $input = <STDIN>; chomp $input; if ((exists $hoa{$input}) and $input eq (@{$hoa{arraya}})) { print (@{$hoa{arraya}}); }

Replies are listed 'Best First'.
Re^2: specific array in hash of arrays
by ikegami (Patriarch) on Oct 09, 2008 at 10:55 UTC

    moritz explained, so what follows is a solution. Basically, comparing a single value against an array makes so sense. By using grep, the value can be compared against every element of the array.

    #!/usr/bin/perl use strict; use warnings; my %hoa = ( arraya => [qw( dd1 dd2 dd3 dd4 )], arrayb => [qw( gg1 gg2 gg3 gg4 )], arrayc => [qw( cc1 cc2 cc3 cc4 )], ); chomp( my $array_name = <STDIN> ); # e.g. arraya chomp( my $to_find = <STDIN> ); # e.g. dd2 if ( exists( $hoa{$array_name} ) && grep { $_ eq $to_find } @{$hoa{$array_name}} ) { print( @{$hoa{$array_name}}, "\n" ); }

      Though looking up a hash will often be better than doing a linear search along a list. For example:

      #!/usr/bin/perl use strict; use warnings; my %hoh = ( flasha => { dd1 => 1, dd2 => 2, dd3 => 3, dd4 => 4 }, flashb => { gg1 => 1, gg2 => 2, gg3 => 3, gg4 => 4 }, flashc => { cc1 => 1, cc2 => 2, cc3 => 3, cc4 => 4 }, ); for ([qw(flasha dd4)], [qw(glashz gg2)], [qw(flashc zz)], [qw(flashc c +c1)]) { my ($array_name, $to_find) = @$_ ; if (exists $hoh{$array_name}->{$to_find}) { print( "$array_name contains $to_find\n" ); } }
      noting that exists stops looking, without complaint, if $hoh{$array_name} doesn't exist.

      If the list is a trivial length, then List::Util::first at least stops looking when it gets a match.

      I don't know what you need to do having discovered the match... the above allows you to map "array name" and "to_find" to anything you like -- the numbers above are for illustration, only !

      If you're only interested in existence, then

      flasha => { map { ($_, undef) } qw(dd1 dd2 dd3 dd4) },
      will serve.

        if (exists $hoh{$array_name}->{$to_find}) {
        should normally be
        if ( exists( $hoh{$array_name} ) && exists( $hoh{$array_name}->{$to_find} ) ) {

        to prevent autovivification of entries into %hoh. That might not matter here, though.

      I think you answered my question as I was writing it! Awesome thanks.
Re^2: specific array in hash of arrays
by moritz (Cardinal) on Oct 09, 2008 at 10:35 UTC
    To satisfy the first condition (exists $hoa{$input}) $input has to be any of arraya, arrayb, arrayc. To satisfy the second condition, $input has to be equal to whatever @{$hoa{arraya}} stringifies to, which is probably 4 (because it's an array in scalar context, giving you the number of items in the array).

    Since no string is both equal to array$something and to 4 at once, you'll never get output from that script.

      I see. Would it be possible then to change the second condition in order to make sure that;
      $input has to be equal to arraya or @{$hoa{arraya}}?
      After that I will also need to iterate over each value of arraya... Err another thing I was thinking about was that
      there might be a different way to grab a specific array that exists inside a hash. Lets say I have 50
      arrays inside my hash and I want to do something to each value of a specific array based on <STDIN>. I dont want
      to right out 50 elsif statements... please help!
        I see. Would it be possible then to change the second condition in order to make sure that; $input has to be equal to arraya or @{$hoa{arraya}}?

        Sure, but do you really want that? Are you aware that @{$hoa{arraya}} will again give you 4 when used in a string comparison.

        If you mean things like "has to be equal to any element in @{$hoa{arraya}}" you have to say it that way. We can't guess what you want, so you have to be precise when you say what you want.

        Lets say I have 50 arrays inside my hash and I want to do something to each value of a specific array based on <STDIN>. I dont want to right out 50 elsif statements... please help!

        We might help you, but you have to be more specific. based on <STDIN>" is not specific. What exactly do you want? search an array in which the line from STDIN occurs? Or select an array based on its name, and then do something with that array?