Yang
Yang

Reputation: 1323

Perl using 'map' to rewrite these codes

Can I use 'map' or some similar function to make the codes simpler?

# $animal and @loads are pre-defined somewhere else.

my @bucket;

foreach my $item (@loads) {

    push @bucket, $item->{'carrot'} if $animal eq 'rabbit' && $item->{'carrot'};

    push @bucket, $item->{'meat'} if $animal eq 'lion' && $item->{'meat'};

}

Upvotes: 0

Views: 70

Answers (2)

daotoad
daotoad

Reputation: 27183

This question would be easier to answer authoritatively with a bit more sample data. As it is I need to make a lot of assumptions.

Assuming:

@loads = (
    { carrot => 47, meat => 32, zebras => 25 },
    { carrot => 7,  zebras => 81 },       
);

and @buckets should look like:

@buckets = ( 47, 32, 7 ); 

when @animals looks like:

@animals = qw/ rabbit lion /;

Here's a maptastic approach. To understand it you will need to think in terms of lists of values as the operands rather than scalar operands:

my @animals = qw/ rabbit lion /;
my %eaten_by = (
    lion   => 'meat',
    rabbit => 'carrot',
    mouse  => 'cheese',
);

# Use a "hash slice" to get a list of foods consumed by desired animals.
# hash slices let you access a list of hash values from a hash all at once.
my @foods_eaten = @eaten_by{ @animals };

# Hint: read map/grep chains back to front.
#       here, start with map @loads and then work back to the assignment
my @bucket =
    grep $_,                   # Include only non-zero food amounts
    map @{$_}{@foods_eaten},   # Hash slice from the load, extract amounts of eaten foods.
    map @loads;                # Process a list of loads defined in the loads array

Rewritten in a verbose nested loop you get:

my @buckets;
for my $item ( @loads ) {
    for my $animal ( @animals ) {
        my $amount = $item{ $eaten_by{$animal} };
        next unless $amount;

        push @buckets, $amount;
    }
}

Which one to use? It all depends on your audience--who will be maintaining the code? Are you working with a team of Perl hackers featuring 4 of the perl5porters? use the first one. Is your team composed of one or two interns that come and go with the seasons who will spend 1% of their time working on code of any kind? Use the second example. Likely, your situation is somewhere in the middle. Use your discretion.

Happy hacking!

Upvotes: 0

tripleee
tripleee

Reputation: 189587

Are you looking for something like this?

%foods = ( 'lion' => 'meat', 'rabbit' => 'carrot');

# ...

foreach my $item (@loads) {
    push @bucket, $item->{$food{$animal}} if $item->{$food{$animal}};
}

Upvotes: 3

Related Questions