http://qs321.pair.com?node_id=782436

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

Given the following:
my $pages; push (@{$pages}, { 'name' => 'Home', 'url' => '/' }); push (@{$pages}, { 'name' => 'About', 'url' => '/html/about.html' }); push (@{$pages}, { 'name' => 'Location', 'url' => '/html/loc.html' });
Is there a clean (simple) way of adding an additional hash element (i.e. 'flag' => 1) to the array where "url" eq "/html/about.html" without having to itterate though the entire data structure? I've done it with nested foreach/while loops but I imagine this can be done much nicer with map, but I haven't had any success.

Thanks!

Replies are listed 'Best First'.
Re: Clean way of adding values to complex data structure
by blokhead (Monsignor) on Jul 22, 2009 at 21:00 UTC
    No need to nest loops. The condition you mentioned can be checked without iterating through each entire hash. You still have to iterate through the array, though.
    for (@$pages) { $_->{flag} = 1 if $_->{url} eq "/html/about.html"; }
    If you want to get really fancy, it can be a one liner, but I think that using logical connectives (and/or) for flow control hurts readability, especially in a complex statement with modifiers.
    $_->{url} eq "/html/about.html" and $_->{flag} = 1 for @$pages;

    blokhead

      Just what I was looking for... thanks!
Re: Clean way of adding values to complex data structure
by ikegami (Patriarch) on Jul 22, 2009 at 21:09 UTC

    without having to itterate though the entire data structure?

    Of course not. You can't inspect the url of every page without visiting them.

    Sets the flag for about pages, leaves it untouched for others:

    $_->{flag} = 1 for grep { $_->{url} eq '/html/about.html' } @$pages;

    Sets the flag for about pages, clears it for others:

    $_->{flag} = ( $_->{url} eq '/html/about.html' ) for @$pages;