What's the difference between grep and map in Perl?

前端 未结 6 741
逝去的感伤
逝去的感伤 2020-12-31 06:50

In Perl both grep and map take an expression and a list, and evaluate the expression for each element of the list.

What is the difference b

相关标签:
6条回答
  • 2020-12-31 07:05

    I find that it's helpful to think think about grep() and map() in their most general form:

    grep {BLOCK} LIST   
    map  {BLOCK} LIST
    

    grep() is a filter: it returns the subset of items from LIST for which BLOCK returns true.

    map() is a mapping function: send a value from LIST into BLOCK, and BLOCK returns a list of 0 or more values; the combined set of all of those calls to BLOCK will be the ultimate list returned by map().

    0 讨论(0)
  • 2020-12-31 07:06

    Think of grep as map with a filter. map iterates and provides an opportunity to do something with every item. For example these two lines are equivalent:

    my @copy = @original;
    my @copy = map {$_} @original;
    

    Similarly, these two are equivalent:

    my @copy = grep {-f $_} @original;
    
    @copy = ();
    for (@original)
    {
      push @copy, $_ if -f $_;
    }
    

    grep provides the ability to insert a conditional, and therefore becomes a filter.

    0 讨论(0)
  • 2020-12-31 07:11

    grep returns those elements of the original list that match the expression, while map returns the result of the expression applied to each element of the original list.

    $ perl -le 'print join " ", grep $_ & 1, (1, 2, 3, 4, 5)'
    1 3 5
    $ perl -le 'print join " ", map $_ & 1, (1, 2, 3, 4, 5)'
    1 0 1 0 1
    

    The first example prints all the odd elements of the list, while the second example prints a 0 or 1 depending on whether the corresponding element is odd or not.

    0 讨论(0)
  • 2020-12-31 07:11

    Facetiously: grep gives its block scalar context, map gives its block list context. (And BLOCK foreach LIST gives its block void context.)

    0 讨论(0)
  • 2020-12-31 07:15

    One other thing about grep: in a scalar context it tells you how many items it found. This can be useful if you don't really want a second list, but you do want to know how many items of a certain kind there are.

    my @numbers = qw/1 2 3 4 5 6/;
    
    my @odd_numbers  = grep { $_ & 1 } @numbers; # grep returns (1, 3, 5)
    
    my $how_many_odd = grep { $_ & 1 } @numbers; # grep returns 3
    

    Edit: Since the OP asked in a comment, I should say that you can use map in a scalar context in the same way. The point wasn't that grep is the only one of the two that can do this, but that it sometimes comes in handy to do this with grep.

    0 讨论(0)
  • 2020-12-31 07:22

    map applies a function to all elements in a list and returns the result.

    grep returns all elements in a list that evaluate to true when a function is applied to them.

    my %fruits = (
      banana => {
        color => 'yellow',
        price => 0.79,
        grams => 200
      },
      cherry => {
        color => 'red',
        price => 0.02,
        grams => 10
      },
      orange => {
        color => 'orange',
        price => 1.00,
        grams => 225
      }
    );
    
    my %red_fruits = map { $_ => $fruits{$_} }
                       grep { $fruits{$_}->{color} eq 'red' }
                         keys(%fruits);
    
    my @prices = map { $fruits{$_}->{price} } keys(%fruits);
    my @colors = map { $fruits{$_}->{color} } keys(%fruits);
    my @grams  = map { $fruits{$_}->{grams} } keys(%fruits);
    
    # Print each fruit's name sorted by price lowest to highest:
    foreach( sort { $fruits{$a}->{price} <=> $fruits{$b}->{price}} keys(%fruits) )
    {
      print "$_ costs $fruits{$_}->{price} each\n";
    }# end foreach()
    
    0 讨论(0)
提交回复
热议问题