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

Hi, kind of a newbie to Perl. I sometimes use map and grep in programs, but only after taking examples from the books. The problem is that after reading about them, I still can't -quite- grok the difference. Can anyone give a simple example to demonstrate?

Replies are listed 'Best First'.
Re: Map and Grep
by chromatic (Archbishop) on Dec 07, 2000 at 03:07 UTC
    map applies an expression to each element in a list, creating a new list:

    my @files_and_sizes = map { [ $_, -s $_ ] } @filenames;

    Here, we have an array of filenames. We use map to iterate over each element, creating an anonymous array consisting of the filename and the size of the file -- for each filename. Those end up in the array on the left hand side. (Read map statements left to right.)

    There's nothing that says that the map block has to return anything related to the source list:

    my @useless = map { 1 } qw( this is a silly test ); print "@useless\n";

    grep applies an expression to each element in the list, returning a list of those elements for which the expression evaluated to be true.

    my @set1 = qw (apples oranges pears mangoes); my @set2 = qw (bananas mangoes papayas coconuts); my %first_set; @first_set{@set1} = (); my @union = grep { exists $first_set{$_} } @set2;
    We create two sets, then create a hash with keys from @set1. Our grep statement checks to see if each element returns a true from the block -- that is, it checks to see if each element of @set2 is a valid key in the hash. It returns a list of those keys (only 'mangoes').
Re: Map and Grep
by arturo (Vicar) on Dec 07, 2000 at 03:06 UTC

    grep acts a lot like the *nix "grep" command, i.e. it returns the things that match a certain condition. Baseline idea that should get you going is that the condition you pass to grep acts as a filter: grep grabs the things in one list that match some condition or other and puts them into another.

     my @filtered = grep { length($_) > 15 } @unfiltered;

    gives you a list of the strings in @unfiltered that are 16 characters or greater in length.

    map is more suited to *transforming* the things in the original list. Suppose I want to uppercase every string in a list, I'd do:

    my @uppercased = map { uc($_) } @list_of_strings;

    Warning: arrays and lists are not the same thing in Perl, even though my presentation here might suggest that. Moreover, in scalar contexts, these functions will not return lists, but rather scalar values (e.g grep returns the number of things that match the condition)

    HTH

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

(kudra: map tutorial) Re: Map and Grep
by kudra (Vicar) on Dec 07, 2000 at 03:13 UTC
    After writing my reply I noticed there were already a lot of answers, so instead I will just suggest that you try the map tutorial here if you want to get more comfortable with using map. We don't seem to have a grep tutorial...
Re: Map and Grep
by chipmunk (Parson) on Dec 07, 2000 at 03:10 UTC
    Here's a quick explanation of the difference between map and grep:

    map EXPR, list
    For each element in LIST, map executes EXPR; the result of EXPR is added to the return list.
    grep EXPR, list
    For each element in LIST, grep executes EXPR; if EXPR returned true, the value of $_ is added to the return list, otherwise nothing is added to the return list.

    grep EXPR, list can be written as map { EXPR ? $_ : ()} LIST , and
    map EXPR, list can be written as grep { $_ = EXPR; 1 } @tmp = LIST (@tmp is necessary because assigning to $_ inside a grep or map changes the original array.)
Re: Map and Grep
by repson (Chaplain) on Dec 07, 2000 at 07:06 UTC
    Just to add something else, here is how map and grep would look if they didn't exist.
    # @out = map { EXPRESSION } @in my @out; foreach $_ ( @in ) { push @out, EXPRESSION; } # @out = grep { CONDITION } @in my @out; foreach $_ ( @in ) { push @out, $_ if CONDITION; }
    Using the functions map and grep saves us typing these commonish constructs every time we need them.
    Perl function list: <LAZY> map grep </LAZY> for foreach
Re: Map and Grep
by damian1301 (Curate) on Dec 07, 2000 at 03:06 UTC
    I think the difference is that grep evaluates the EXPR in Boolean context and returns it if its true, while map evaluates the EXPR for an element in list and returns the changes. I don't really know much else because I haven't gotten into using them much. If that helps that Im happy, Later.

    Wanna be perl hacker.
    Dave AKA damian