Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

easy way to extract a hash from an array?

by rmexico (Novice)
on Feb 08, 2006 at 16:46 UTC ( #528841=perlquestion: print w/replies, xml ) Need Help??
rmexico has asked for the wisdom of the Perl Monks concerning the following question:

if i have the following:
while (blah) { ## do something %person = ('fname => $fname, 'lname' => $lname); push @PEOPLE, \%person; }
is there an easy way to tell if @PEOPLE contains a person named "John" w/o looping over the array and extracting each hash then comparing. The following works, but seems long-winded to me:
foreach my $ppl (@PEOPLE) { my $fname = $ppl->{'fname'}; .... }
easier way?

Replies are listed 'Best First'.
Re: easy way to extract a hash from an array?
by davido (Archbishop) on Feb 08, 2006 at 16:53 UTC

    Your first snippet may contain a bug. You're pushing the same %person into @PEOPLE every time through the loop, unless %person is declared lexically on each iteration of the loop (ie, there has to be a my %person in the loop).

    There isn't a way to avoid looping when you're looking for something inside of an array. You can grep, but that's still a loop:

    my( @matches ) = grep { $_->{'fname'} eq 'John' } @PEOPLE;


Re: easy way to extract a hash from an array?
by nobull (Friar) on Feb 08, 2006 at 18:20 UTC
    If you are doing a lot of such lookups then you may find it worthwhile to index @PEOPLE.
    my %PEOPLE_index; for my $ppl (@PEOPLE) { while ( my ( $k,$v) = each %$ppl ) { push @{$PEOPLE_index{$k}{$v}} => $ppl; } } for my $ppl ( @{$PEOPLE_index{fname}{John}} ) { #.... }
Re: easy way to extract a hash from an array?
by MCS (Monk) on Feb 08, 2006 at 17:15 UTC

    How else would you find something other than look for it? Personally I think two lines of code isn't exactly long winded. You could write a subroutine if you have to do this a few times that accepts your AoH and the string you are searching for. But yes, you still have to loop through it.

Re: easy way to extract a hash from an array?
by beachbum (Beadle) on Feb 08, 2006 at 18:47 UTC

    If your goal is to search on first name, then you might not want to use an array anyhow....

    my %people = (); while (blah) { ## do something $people{$fname}{$lname}++; } my $search_term = 'John'; if (exists $people{$search_term}){ # do stuff. }
Re: easy way to extract a hash from an array?
by johngg (Abbot) on Feb 09, 2006 at 10:28 UTC
    Given that you have reasons to hold your people in a list then a quick way to search for particular first names is to index them as other replies have suggested. You can build the index as you build the @PEOPLE list and if you make the index a HoL with key being name and value being record no. in @PEOPLE you can extract all of your Johns using a slice.
    #!/usr/local/bin/perl -w # use strict; our @PEOPLE = (); our $rhFirstNameIdx = {}; our $recCt = 0; while(<DATA>) { chomp; my ($fname, $lname) = split; push @PEOPLE, {fname => $fname, lname => $lname}; push @{$rhFirstNameIdx->{$fname}}, $recCt ++; } our $wanted = 'John'; our @found = @PEOPLE[@{$rhFirstNameIdx->{$wanted}}]; print "First - $_->{fname}, Last - $_->{lname}\n" for @found; __END__ Fred Bloggs Charley Farley John Doe Peter Piper Mary Poppins John Smith Bill Bailey

    The little script above illustrates this and prints out the entries for John Doe and John Smith.



Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://528841]
Approved by davido
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2018-01-22 16:55 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (235 votes). Check out past polls.