449,023 Members | 929 Online Need help? Post your question and get tips & solutions from a community of 449,023 IT Pros & Developers. It's quick & easy.

# map, filter & reduce...

 P: n/a 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
4 Replies

 P: n/a "Ben" 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, seq2) 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*item > 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([ , ,  ]) 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([ , ,  ], []) 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. 