Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Using map and grep to Sort one list using another list

by AntsPants (Novice)
on Feb 05, 2007 at 12:51 UTC ( #598282=perlquestion: print w/replies, xml ) Need Help??
AntsPants has asked for the wisdom of the Perl Monks concerning the following question:

Can I use map instead of the foreach in this bit of code? i have two lists. One has the keys (@keys) I'd like to look for in the other list (@records). The records that have the key are passed through to a @result list. If the result list is non-empty, it goes to the final list as the @result list may be overwritten in the next iteration. Or, is there a totally better alforithm to do this? I have googled and looked on this site before posting but nothing stood out and hit me in the face but I'm sure a more elegant perl way of doing it exists ;)
my @keys = ( qw|a e i o u| ); my @records = (); push @records, '1|2|3|d|4'; push @records, '1|2|3|a|4'; push @records, '1|2|3|d|4'; push @records, '1|2|3|o|4'; my @final = (); my @result = (); my $re = ''; foreach my $key ( @keys ) { @result = grep{ m/^\d\|\d\|\d\|$key\|\d$/ } @records; push @final, [ @result ] if @result; } print map{ "@{ $final[$_] }\n" } 0..$#final;
Merci bien, Perl Monkers!!

Replies are listed 'Best First'.
Re: Using map and grep to Sort one list using another list
by davorg (Chancellor) on Feb 05, 2007 at 13:28 UTC

    I think the (ahem!) key here is to convert your @keys array into a hash to make it easier to check for the existance of keys in your data line.

    my @keys = ( qw|a e i o u| ); my %keys = map { $_ => 1 } @keys; my @records = ( '1|2|3|d|4', '1|2|3|a|4', '1|2|3|d|4', '1|2|3|o|4', ); my @final; my @result; foreach (@records) { if ($keys{ (split /\|/)[3] }) { push @result, $_; } } print map { "$_\n" } @result;
      I agree but this morning I spoke to the person who has this problem and they said they wanted to keep the code as lists!!! Will have another friendly chat with them ;)
Re: Using map and grep to Sort one list using another list
by shmem (Canon) on Feb 05, 2007 at 13:16 UTC
    Sure you can use map:
    my @final = grep {@$_} map { my $key = $_; [ grep{ m/^\d\|\d\|\d\|$key\|\d$/ } @records ] } @keys;

    But I am missing the 'sort' bit of the title in your code...


    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      The sort is a mistake. Just keeping you on your toes. Now, no one's gonna believe this but ......... I'm sure while trying to solve this problem I wrote the following code
      my @keys = ( qw|a e i o u| ); my @records = (); push @records, '1|2|3|d|4'; push @records, '1|2|3|a|4'; push @records, '1|2|3|d|4'; push @records, '1|2|3|o|4'; my @final = (); my @result = (); @result = map { my $index = $_; grep{ m/^\d\|\d\|\d\|$keys[$index]\|\d$/ } @records } 0..$#keys; print map{ "$result[$_]\n" } 0..$#result
      which didn;t work. And while replying to your soln, I just re-ran that code and it worked!!!!!!! Hmmmmmmmmmm. Thank you all for replying anyway. I feel such a fool. -Ants
Re: Using map and grep to Sort one list using another list
by wfsp (Abbot) on Feb 05, 2007 at 13:17 UTC
    Here's my go with grep. If you put your keys into a hash you can use exists to see if it's one we want.
    #!C:/Perl/bin/perl.exe use strict; use warnings; my %keys = ( a => undef, e => undef, i => undef, o => undef, u => undef, ); my @records = qw{ 1|2|3|d|4 1|2|3|a|4 1|2|3|d|4 1|2|3|o|4 }; my @final = grep { my @flds = split '\|', $_; my $third = $flds[3]; exists $keys{$third} } @records; print "@final\n";
    You could make that shorter but this way gives you a better idea of what's happening. output:
    1|2|3|a|4 1|2|3|o|4
Re: Using map and grep to Sort one list using another list
by RMGir (Prior) on Feb 05, 2007 at 13:20 UTC
    Interesting problem. Maybe you could do something with a hash for your keys? This doesn't completely match your spec, although it matches your example. Perhaps you can adapt this for your needs...
    my %keys = ( a=>1, e=>2, i=>3, o=>4, u=>5, ); my @records = (); push @records, '1|2|3|d|4'; push @records, '1|2|3|a|4'; push @records, '1|2|3|d|4'; push @records, '1|2|3|o|4'; my @final = (); my @result = (); my $re = ''; map {my @flds=split /\|/; push @{$final[$keys{$flds[3]}||0]},$_} @reco +rds; # note that entry 0 is where the unmatched elements wind up... print map{ "@{ $final[$_] }\n" } grep defined $final[$_],1..$#final;
    Maps used only for their side effects are kinda wierd, though. I'd replace the map with a foreach(@records) block so it's clearer what you're doing.
    foreach(@records) { my @flds=split /\|/; push @{$final[$keys{$flds[3]}||0]},$_; }

Re: Using map and grep to Sort one list using another list
by Moron (Curate) on Feb 05, 2007 at 13:43 UTC
    Do you mean like this?
    my @result = map { my $key = $_; grep m/^\d\|\d\|\d\|$key\|\d$/, @records } @keys +;


    Free your mind

      that is what I meant and that is what I tried in testing. see reply to first post ;) As I said, I feel an idiot!!
      You will have undefined values in your @result array.

      the above is plain wrong--


        I don't see that happening. Perhaps I have missed something.

        use strict; use warnings; use Data::Dumper; my @keys = qw{a e i o u}; my @records = qw{ 1|2|3|d|4 1|2|3|a|4 1|2|3|d|4 1|2|3|o|4}; my @result = map { my $key = $_; grep { m{^(?:\d\|){3}$key\|\d$} } @records } @keys; my $dd = Data::Dumper->new([\@result], [qw{*result}]); print $dd->Dumpxs();


        @result = ( '1|2|3|a|4', '1|2|3|o|4' );



        My take on this was rather that when the grep fails to produce a match, it returns an empty list to map which then operates on no extra entries - i.e. doing nothing rather than constructing an undefined value.


        Free your mind

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://598282]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2017-02-20 02:01 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (293 votes). Check out past polls.