Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

In search of elegant code - looking deeply into a hash

by davidfilmer (Sexton)
on Mar 02, 2016 at 01:40 UTC ( [id://1156600]=perlquestion: print w/replies, xml ) Need Help??

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

Masters - Suppose I have a hash like this:
my %uid =( 1 => { 'firstname' => 'Alice', 'lastname' => 'Foo', }, 2 => { 'firstname' => 'Bob', 'lastname' => 'Bar', }, );
I want to find out Alice's last name. Of course, I could just slog through the hash:
foreach my $key( keys %uid ){ if( $uid{$key}{'firstname'} eq 'Alice' ){ print "lastname is $uid{$key}{'lastname'}\n"; } }
But that seems inelegant. Is there a more elegant way?

Replies are listed 'Best First'.
Re: In search of elegant code - looking deeply into a hash
by NetWallah (Canon) on Mar 02, 2016 at 03:49 UTC
    How about this:
    my @possible_last_names = map {$_->{lastname}} grep {$_->{firstname} eq "Alice"} values %uid; # Returns ("Foo")

            "Think of how stupid the average person is, and realize half of them are stupider than that." - George Carlin

Re: In search of elegant code - looking deeply into a hash
by beech (Parson) on Mar 02, 2016 at 03:13 UTC

    But that seems inelegant. Is there a more elegant way?

    Yes, wrap it in a sub

    if( my $lastname = uid_lastname( \%uid, 'Alice' ) ){ print "lastname is $lastname\n"; }

    Other "elegant" options might include Data::Diver , Data::DPath, Data::Path/Data::Path

    update: with dpath you can lookup the lastname like so

    my $lastname = dpath( q{/*/firstname[ value =~ /Alice/i ]/../lastname} + )->match( \%uid ) my $lastname = dpath( q{/*/firstname/.[ value eq 'Alice' ]/../lastname +} )->match( \%uid ) ;
Re: In search of elegant code - looking deeply into a hash
by Laurent_R (Canon) on Mar 02, 2016 at 07:26 UTC
    The issue is not so much that the code is "inelegant", but that the data structure is not well adapter to your query. Perhaps you should rethink the data structure. Or, if you can't and if you have to do that often, then add a lookup table with the first names as the key and a list of records as a value. This will take some time to build but make queries faster and easier thereafter.
Re: In search of elegant code - looking deeply into a hash
by flowdy (Scribe) on Mar 02, 2016 at 12:18 UTC

    Certainly depending on what you want to do, you should also consider using a database, at least SQLite that does not require a running database server, in favour of implementing a little quick-and-dirty database engine like this. It is much more scalable. This at least would deserve the attribute "elegant" in my eyes, given your example code that suggests expansion to other data associated with those people.

Re: In search of elegant code - looking deeply into a hash
by Anonymous Monk on Mar 02, 2016 at 13:25 UTC

    More concise, or just more obfuscated?

    print +{map @$_{qw(firstname lastname)}, values %uid}->{Alice};

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1156600]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-03-29 08:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found