By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,899 Members | 1,066 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,899 IT Pros & Developers. It's quick & easy.

map, filter & reduce...

P: n/a
Ben
Hi all,

I'm trying to figure out how how complex map, filter and reduce work
based on the following piece of code from
http://www-106.ibm.com/developerwork...ry/l-prog.html :

bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, combine(xs,ys))
combine = lambda xs,ys: map(None, xs*len(ys), dupelms(ys,len(xs)))
dupelms = lambda lst,n: reduce(lambda s,t:s+t, map(lambda l,n=n:
[l]*n, lst))
print bigmuls((1,2,3,4),(10,15,3,22))

The solution generated by the above code is: [(3, 10), (4, 10), (2,
15), (3, 15), (4, 15), (2, 22), (3, 22), (4, 22)]

I'm stuck on the second line in "map(None, xs*len(ys),
dupelms(ys,len(xs))"... Can someone explain me how the map function
evaluates??

Thanks
Ben
Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a

"Ben" <cr*********@yahoo.com> wrote in message
news:d9**************************@posting.google.c om...
Hi all,

I'm trying to figure out how how complex map, filter and reduce work
based on the following piece of code from
http://www-106.ibm.com/developerwork...ry/l-prog.html :

bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, combine(xs,ys))
combine = lambda xs,ys: map(None, xs*len(ys), dupelms(ys,len(xs)))
dupelms = lambda lst,n: reduce(lambda s,t:s+t, map(lambda l,n=n:
[l]*n, lst))
print bigmuls((1,2,3,4),(10,15,3,22))

The solution generated by the above code is: [(3, 10), (4, 10), (2,
15), (3, 15), (4, 15), (2, 22), (3, 22), (4, 22)]

I'm stuck on the second line in "map(None, xs*len(ys),
dupelms(ys,len(xs))"... Can someone explain me how the map function
evaluates??
In this case, map is (almost) a synonym for zip. It's going to
create a list where each entry is a two item list containing the
corresponding elements from each of the inputs. The first
input is, of course, the result of the multiply, and the second
is whatever the dupelms() call produced.

John Roth
Thanks
Ben

Jul 18 '05 #2

P: n/a
Ben wrote:
Hi all,

I'm trying to figure out how how complex map, filter and reduce work
based on the following piece of code from
http://www-106.ibm.com/developerwork...ry/l-prog.html :

bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, combine(xs,ys))
combine = lambda xs,ys: map(None, xs*len(ys), dupelms(ys,len(xs)))
dupelms = lambda lst,n: reduce(lambda s,t:s+t, map(lambda l,n=n:
[l]*n, lst))
print bigmuls((1,2,3,4),(10,15,3,22))

The solution generated by the above code is: [(3, 10), (4, 10), (2,
15), (3, 15), (4, 15), (2, 22), (3, 22), (4, 22)]

I'm stuck on the second line in "map(None, xs*len(ys),
dupelms(ys,len(xs))"... Can someone explain me how the map function
evaluates??

Thanks
Ben


Do yourself a favour and read on to the sane version that uses a list
comprehension :-) By the way, David Mertz has deliberately obfuscated the
traditional imperative approach by not preserving the block structure and
inserting superfluous comments.

map(None, seq1, seq2) returns a list of tuples (seq1[0], seq2[0]) etc. The
sequence item is substituted with None, if a sequence is exhausted, e. g.
map(None, range(3), range(2)) [(0, 0), (1, 1), (2, None)]
but that doesn't occur here, making zip() instead of map() a better choice.

Putting it all together:
dupelms() takes a list and a length n creating a new list where each item of
the original list is duplicated n times:
dupelms(range(3), 2) [0, 0, 1, 1, 2, 2]
This is then zipped (though by map())
with a list similar to range(2)*3 [0, 1, 0, 1, 0, 1]
map(None, [0,0,1,1,2,2], [0,1,0,1,0,1]) [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]


This last list is then filtered for items (the tuples), that meet the
condition
item[0]*item[1] > 25

To imagine how errorprone this code is and to check how well it scales with
large lists is left as an exercise to the reader...

Peter
Jul 18 '05 #3

P: n/a
Ben wrote:
I'm trying to figure out how how complex map, filter and reduce work
based on the following piece of code from
http://www-106.ibm.com/developerwork...ry/l-prog.html :

bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, combine(xs,ys))
combine = lambda xs,ys: map(None, xs*len(ys), dupelms(ys,len(xs)))
dupelms = lambda lst,n: reduce(lambda s,t:s+t, map(lambda l,n=n:
[l]*n, lst))
print bigmuls((1,2,3,4),(10,15,3,22))


Hi all,

I've played with this example, also. I'd rewritten the example
using zip() and sum(), when I've noticed a quirk of the sum() function.

# keep pairs whose product is greater than 25.
bigmuls=lambda xs,ys:filter(lambda (x,y): x*y>25, combine(xs, ys))

# compute the cross product of two lists.
# combine([1,2],[3,4]) --> [(1, 3), (2, 3), (1, 4), (2, 4)]
combine=lambda xs,ys:zip(xs*len(ys), dupelms(ys, len(xs)))

# duplicate elements of lst n times.
# dupelms([1,2], 3) --> [1, 1, 1, 2, 2, 2]
dupelms=lambda lst,n:sum(map(lambda element,n=n:[element]*n, lst),[])
I'd ran into trouble when I've used sum() naively:

sum([ [1], [2], [3] ])

results in:

TypeError: unsupported operand type(s) for +: 'int' and 'list'
A peek in the language reference:

sum(sequence[, start])
Sums start and the items of a sequence, from left to right,
and returns the total. start defaults to 0. The sequence's
items are normally numbers, and are not allowed to be strings.
The fast, correct way to concatenate sequence of strings
is by calling ''.join(sequence). Note that sum(range(n), m)
is equivalent to reduce(operator.add, range(n), m)
New in version 2.3.
As we can see:
sum(seq, start) is equivalent to reduce(operator.add, seq, start)

but:
sum(seq) is not equivalent to reduce(operator.add, seq)

because: start of sum() defaults to 0. So we must set the
start value explicit to the neutral element for the addition:

sum([ [1], [2], [3] ], [])
The other strange behaviour is:

sum(['my', 'pet', 'fish', 'eric'], '')

results in:

TypeError: sum() can't sum strings [use ''.join(seq) instead]

If there is a special treatment for strings, why doesn't sum()
use ''.join(seq) itself, instead of telling me that I should
use it? But in fact sum() should call operator.add(), even
for strings:
from types import StringType

class MyString(StringType):
# __metaclass__ = type

def __init__(self, value):
StringType.__init__(self, value)

def __str__(self):
return StringType.__str__(self)

def __add__(self, other):
return MyString(str(self) + ' ' + str(other))

my = MyString('my')
pet = MyString('pet')
fish = MyString('fish')
eric = MyString('eric')

# different output (with intent):
print my + pet + fish + eric # --> my pet fish erik
print ''.join([my, pet, fish, eric]) # --> mypetfisheric

# two quirks for sum(), here:
# 1. does not work, because MyString is a subclass of string
# 2. result have an extra unwanted space (if it would work)
print sum( [my, pet, fish, eric], MyString('') )
I would treat this quirks as unpythonic, cause the behaviour
of the sum() function is not generic and not intuitive.

Will this be fixed in future releases of python?

Jul 18 '05 #4

P: n/a
On Wed, Nov 19, 2003 at 11:46:07PM +0100, Jan-Erik Meyer-Lütgens wrote:
[...]
I'd ran into trouble when I've used sum() naively: [...] The other strange behaviour is:

sum(['my', 'pet', 'fish', 'eric'], '')

results in:

TypeError: sum() can't sum strings [use ''.join(seq) instead]

If there is a special treatment for strings, why doesn't sum()
use ''.join(seq) itself, instead of telling me that I should
use it? But in fact sum() should call operator.add(), even
for strings:


There was a duscussion on this in python-dev. See thread starting from

http://mail.python.org/pipermail/pyt...il/034767.html

and Guido's summary at

http://mail.python.org/pipermail/pyt...il/034853.html

..

-Inyeol Lee

Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.