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

I am trying to find the first name that exist in a hash. The keys in the hash are in alphabetical order. When I ran the following code, it will not find "ALEX".

Here is my code:

my %WORD =
('AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL', 'ALEX');
$name = "ALEX B. WILLIAM";
$name =~ /^(\w+) /;
print "WORD = $1\n" if (exists $WORD{$1});

If I re-organize the hash key into something like below, it will find "ALEX".

my %WORD = ('AALIYAH', 'AARON', 'ALEX', 'ABBE', 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL');

Any idea or suggestion?

Thank you.

Replies are listed 'Best First'.
Re: Exists in HASH issue
by simonm (Vicar) on Jul 21, 2003 at 22:26 UTC

    In order to assign to a hash, you must pass in a matching value for every key, which can be arbitrary, ie 'AALIYAH' => 1, 'AARON' => 1, etc.

    A common idiom for this is expressed using map():

    my %WORD = map ( $_ => 1 ), ('AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL', 'A +LEX');
Re: Exists in HASH issue
by jasonk (Parson) on Jul 21, 2003 at 22:27 UTC

    Exists only looks for keys, in your first example ALEX is a value, not a key.

    I suspect you think your has looks like this:

    ( 'AALIYAH' => '', 'AARON' => '', 'ABBE' => '', 'ABBEY' => '', 'ABBI' => '', 'ABBIE' => '', 'ABBIGAIL' => '', 'ALEX' => '', )

    When in reality it looks like this:

    ( 'AALIYAH' => 'AARON', 'ABBE' => 'ABBEY', 'ABBI' => 'ABBIE', 'ABBIGAIL' => 'ALEX', )

    We're not surrounded, we're in a target-rich environment!
(jeffa) Re: Exists in HASH issue
by jeffa (Bishop) on Jul 21, 2003 at 22:29 UTC
    You can't find 'ALEX' in your first data set because you are searching for keys, and 'ALEX' is a value. In your second data set, 'ALEX' is indeed a key. This is why i like to write my hashes out like so:
    my %WORD = ( 'AALIYAH' => 'AARON', 'ABBE' => 'ABBEY', 'ABBI' => 'ABBIE', 'ABBIGAIL' => 'ALEX', );
    so i can easily see which are the keys and which are the values. So, to answer your question - you need to decide whether or not 'ALEX' should be a key or value and search the keys or the values accordingly.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Exists in HASH issue
by Zaxo (Archbishop) on Jul 21, 2003 at 22:34 UTC

    A hash slice is a good way to initialize that sort of thing,

    my %word; @word{'AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL', 'ALEX'} = ();
    though you probably wouldn't hardcode the hash keys in a real application of this kind.

    After Compline,
    Zaxo

Re: Exists in HASH issue
by bobn (Chaplain) on Jul 21, 2003 at 22:35 UTC

    You are not understanding how hashes work. Your code creates a hash, but assigns the value 'ALEX' to the key 'ABBIGAIL'. When you move ALEX earlier in the hash, you also put him in the 'odd' posiiton, so ALEX bacame a key, assigned the value 'ABBE',

    Data::Dumper is very useful in this regaerd:

    use Data::Dumper; my %WORD = ('AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL', 'A +LEX'); print "FIRST HASH:\n"; print Dumper(\%WORD); my %WORD = ('AALIYAH', 'AARON', 'ALEX', 'ABBE', 'ABBEY', 'ABBI', 'ABBI +E', 'ABBIGAIL'); print "SECOND HASH:\n"; print Dumper(\%WORD);

    produces:

    FIRST HASH: $VAR1 = { 'ABBI' => 'ABBIE', 'ABBIGAIL' => 'ALEX', 'AALIYAH' => 'AARON', 'ABBE' => 'ABBEY' }; SECOND HASH: $VAR1 = { 'ALEX' => 'ABBE', 'AALIYAH' => 'AARON', 'ABBEY' => 'ABBI', 'ABBIE' => 'ABBIGAIL' };

    Also, note that the keys to the hash are not in alphabetical order. They are in an order picked by perl, which you cannot count on.

    If you need to operate on has keys sorted alphabeitcally, you need to sort them yourself, for example:

    for ( sort keys %WORD ) { print "$_: $WORD{$_}\n" }

    some or all code untested.

    --Bob Niederman, http://bob-n.com
Re: Exists in HASH issue
by antirice (Priest) on Jul 21, 2003 at 22:31 UTC

    A hash consists of key, value pairs. Only keys can be tested for whether or not they exist, as shown in this snippet:

    use Data::Dumper; my %WORD = ('AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'ABBIGAIL', 'A +LEX'); print Dumper(\%WORD); __DATA__ $VAR1 = { 'ABBI' => 'ABBIE', 'ABBIGAIL' => 'ALEX', 'AALIYAH' => 'AARON', 'ABBE' => 'ABBEY' };

    You should be using a hash slice instead.

    my @names = ('AALIYAH', 'AARON', 'ABBE' , 'ABBEY', 'ABBI', 'ABBIE', 'A +BBIGAIL', 'ALEX'); my %WORD; @WORD{@names} = (); ...

    Take a look at perldoc perldata for more information on the wonderful data structures in perl as well as some nifty tricks that can be performed upon them.

    Hope this helps.

    antirice    
    The first rule of Perl club is - use Perl
    The
    ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Exists in HASH issue
by runrig (Abbot) on Jul 21, 2003 at 22:34 UTC
    If you want to define keys and don't care about values (i.e. you're only going to see if a key exists), you can use undef:
    my %word; undef @word{qw(AALIYAH AARON ALEX ...)}; print "exists!\n" if exists $word{ALEX}; # Or if you want to make sure the values are set to undef: my %word; @word{qw(AALIYAH AARON ...)} = undef;
Re: Exists in HASH issue
by snadra (Scribe) on Jul 22, 2003 at 08:17 UTC
    Hello,

    you should read
    perldoc perlvar
    first, to understand how hashes work. As said before, they are not sorted in any way.
    But you can print them out sorted or do something else with them in a sorted way.
    This would cause a numerical order:
    foreach (sort {$a <=> $b} keys %hash) { # do something with $hash{$_} ... }
    To sort them lexically just use:
    foreach (sort keys %hash) { # ... }
    Read 'perldoc -f sort' for more information.

    snadra
Re: Exists in HASH issue
by Theo (Priest) on Jul 22, 2003 at 14:49 UTC
    A point the other posters didn't mention, is that your variable data looks more like an array (@WORD) than a hash (%WORD). I don't understand what you're doing to it later - I'm only in chapter 7 of "Learning Perl" - so maybe you do need a hash. But ask yourself if your lookup would work just as well with an array variable?

    -ted-