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

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

I'm just starting to get to grips with map and wondering what more I can do with it. Is it possible to do conditional mapping? To take the example in map, say I have an array
my @array = qw/ foo bar baz bodkin /;
and I want to make a hash using all but words beginning in 'f' as values,
my %hash2 = (); foreach $_ (@array) { $hash2{getkey($_)} = $_ unless /^f/; }
works, but is there an equivalent usage with map?
my %hash1 = map {getkey($_) => $_ unless /^f/} @array;
doesn't work.

Am I barking up the wrong tree? Which tree would you recommend?

§ George Sherston

Replies are listed 'Best First'.
Re: Conditional Map?
by broquaint (Abbot) on Oct 07, 2002 at 11:33 UTC
    This sort of situation suits for just fine and doesn't really fit with a sole map as it's really designed towards applying a transform to a list, not iterating over one. You could however achieve your goal using map and grep in conjunction e.g
    my %hash1 = map { getkey($_) => $_ } grep { !/^f/ } @array;

    HTH

    _________
    broquaint

Re: Conditional Map?
by blakem (Monsignor) on Oct 07, 2002 at 11:45 UTC
    To "zero out" an element using map, simply return an empty list for that value...
    my @evens = map { $_%2 ? () : $_ } 1..10;
    So, you'd need to do something like this:
    my %hash = map { /^f/ ? () : (getkey($_) => $_) } @array;

    -Blake

Re: Conditional Map?
by seattlejohn (Deacon) on Oct 07, 2002 at 14:04 UTC
    map's best friend is grep, which returns the subset of list elements matching a condition. So you could start by selecting just the array elements you want: grep {substr($_,0,1) ne 'f'} @array

    This returns a list consisting of qw(bar baz bodkin), which should be just what you need for your map: my %hash1 = map {getkey($_) => $_} grep {substr($_,0,1) ne 'f'} @array;