Re: sort by extension

From: James Edward Gray II (james_at_grayproductions.net)
Date: 07/28/04


Date: Wed, 28 Jul 2004 13:46:07 -0500
To: John West <john.west@gmail.com>


(Let's keep our discussion on the list for all to help and learn,
please.)

On Jul 28, 2004, at 12:55 PM, John West wrote:

> James Edward Gray II <james@grayproductions.net>
>
> On Wed, 28 Jul 2004 12:41:08 -0500, James Edward Gray II wrote
>>
>> I'm never one to abuse working code, but if your definition of
>> "better" has something to do with sorter, a simple Schwartzian
>> Transformation seems to work:
>>
>> @input = map { $_->[0] }
>> sort { lc($a->[1]) cmp lc($b->[1]) }
>> map { m/\.([^.]+)$/ ? [$_, $1] : [$_, ''] } @input;
>
> Thanks for the suggestion. I'm not really sure what I mean by better
> - seems like there are tradeoffs between readability, performance and
> length; mine is too long. Unfortunately I can't follow this code (I'm
> not a big fan of map or grep) so I probably wouldn't take this
> approach unless it really improves performance.

Not a "fan" of map() and grep() or just don't understand them? I'm
hoping it's the second, since the first doesn't make much sense to me.
Luckily, we can fix the second.

map() is generally just a shorthand for a foreach loop. You feed it a
list and a chunk of processing code. It runs the code on each item in
the list and spits out a list that is the results the code returned for
each item. Example:

my @names = qw(JAMES BOB JEFF);

my @title_case = map { "\u\L$_" } @names; # process each name

print "@title_case\n"; # prints James Bob Jeff

Let's apply that thinking to demystify the code I offered you. It's
easier to read that code bottom to top, so let's start with:

map { m/\.([^.]+)$/ ? [$_, $1] : [$_, ''] } @input;

That processes each element of the array input. The processing code
looks for an extension and returns a two element array (by reference)
that contains the original string in the first slot and the extension
in the second (or an empty string, if none could be found). Our
modified list of originals and extensions side-by-side is then handed
up the chain to:

  sort { lc($a->[1]) cmp lc($b->[1]) }

Are you a "fan" of sort()? It works just like map() and grep().

You feed it a list, a condition or conditions you want it sorted on and
it returns the results. My condition here is simply what you asked
for, by extension case-insensitively. We have our answer at this
point, but not in the format expected so we feed it to one more map():

@input = map { $_->[0] }

This is simply the reverse of the first map(). Where it turned
everything into a two-part list (original and extension), this one
returns everything to it's original format, discarding referenced
arrays and extensions. The result of that final operation is then
store back in the array.

grep() is more a list filtering tool. Feed it a list, tell it what
you're looking for, and you get just those elements back. Example:

my @numbers = (104, 3, 102, 1, 100);

my @small_numbers = grep { $_ < 10 } @numbers; # search list

print "@small_numbers\n"; # prints 3 1

map() and grep() are powerful tools, because they allow us to specify
what work we want done. You can argue that they hurt readability in
some cases, as long as I can argue that they help it in others.
Eventually, when you're learning any language, you have to start
picking up the slang too, so you can speak it like the pros do.
Nothing wrong with that.

Work with them a little and see if you can't put them to good use. I
think you'll surprise yourself and hopefully, become a "fan"...

James



Relevant Pages

  • Re: usage of grep and map
    ... Although I read the usage for grep and map using ... perldoc -f grep or map I don't think I really get the ... array reference every time. ...
    (perl.beginners)
  • Re: usage of grep and map
    ... print "result of using map function\n",dump ... result of using grep function ... Do You Yahoo!? ... Mail has the best spam protection around ...
    (perl.beginners)
  • Re: usage of grep and map
    ... scalar context. ... These properties make grep useful for simply ... So map function returns the transformed or changed ... for/foreach loops/statement modifiers) they alias $_ ...
    (perl.beginners)
  • Re: usage of grep and map
    ... scalar context. ... These properties make grep useful for simply ... So map function returns the transformed or changed ... Perl provides four basic list transformation functions: ...
    (perl.beginners)
  • Re: Setting echoed string to command
    ... > many files in the target directory with the same file extension (I get ... > an error message if I try a simple grep). ... If they are fixed strings then something like ... echo "Enter strings to search for, one per line, type CTRL-D to end" ...
    (comp.unix.shell)