[Tutor] map, filter and lambda functions
Sheila King
sheila@thinkspot.net
Wed, 22 Aug 2001 20:59:25 -0700
On Thu, 23 Aug 2001 01:01:58 +0100, "Allan Crooks"
<allan.crooks@btinternet.com> wrote about Re: [Tutor] map, filter and
lambda functions:
:On 22 Aug 2001, at 16:16, Sheila King wrote:
:
:> Here's the new, shorter version:
:>
:> checklist = string.split(filetext, "\n")
:> checklist = filter(lambda x: x != '', checklist)
:> checklist = map(lambda x: string.strip(x), checklist)
:> checklist = map(lambda x: string.upper(x), checklist)
:My opinion is, the best version is the one which makes you smile
:more. :) Out of the two, I like the second one more.
Well, I really was asking for an outside opinion, and someone who knew a
bit more about optimizing the code.
:> Is there a way to do this without lambda functions, or are they
:> pretty much needed in this case?
:
:You don't need to put lambda functions, you can just provide
:string.strip and string.upper without using lambda what-so-ever.
Are you sure that you can do this without lambda? I tried today, and
couldn't get it to work without lambda.
>>> mylist
['a', 'b', 'c', '']
>>> mylist = map(string.upper(x), mylist)
Traceback (most recent call last):
File "<pyshell#6>", line 1, in ?
mylist = map(string.upper(x), mylist)
NameError: name 'x' is not defined
>>> mylist = map(string.upper(), mylist)
Traceback (most recent call last):
File "<pyshell#7>", line 1, in ?
mylist = map(string.upper(), mylist)
TypeError: upper() takes exactly 1 argument (0 given)
>>>
If I do it with no argument, it complains that it requires an argument.
If I put an argument there, it complains that it has never heard of that
variable before.
That's what prompted me to try the lambda functions. I figured, I could
thereby (essentially) declare the variable x before I used it.
:I would personally, however, write this:
:
:checklist = map (lambda x: x.strip().upper(), checklist)
:
:or, if Python 1.5.2 doesn't like that:
No, 1.5.2 requires the string module to do string functions.
:checklist = map (lambda x: string.upper(string.strip(x)), checklist)
:
:Which reduces it down to one line. But you might not want that.
Not too readable, IMO.
:You could also replace the lambda function that's used in filter with
:"None". IIRC, that will only return objects which have a positive
:truth value (in the case of strings, this would only be non-empty
:strings).
Hmm. That seems to work:
>>> mylist
['a', 'b', 'c', '']
>>> filter(None, mylist)
['a', 'b', 'c']
>>>
Now I'm curious as to *why* it works. 'None' doesn't strike me as a
function that returns a value. Although, it says in the documentation
somewhere, that None on map works as the identity function. This didn't
bother me, though. It seemed like "No map...gives you same thing you
started with."
:If you were really daring, you could put all that into one large
:function:
:
:checklist = map (string.upper, map (string.strip, filter (None,
:string.split(filetext, "\n"))))
:
:That *might* work, I can't be bothered to test it. :)
OK, two remarks on this:
First of all, does putting it all in one line make it run faster or more
efficiently? My intuition says, "No".
Secondly, it's definitely harder to follow. I would be very disinclined
to writing it like that. Having the code be compressed into a single
line really isn't that appealing.
:Use whatever version you are happiest with. I'd go with whatever
:version is easier to understand when you read it, which, out of the
:two you've given us, would be the second one.
That's an interesting remark. Until today, I wouldn't have found those
filter and map, or lambda functions easy to read and understand.
Something clicked today, and now I'm fine with them. But before, I would
have preferred the nested loop stuff I had originally.
--
Sheila King
http://www.thinkspot.net/sheila/
http://www.k12groups.org/