enhanced map function

P

Patrick

Hi,

The build-in map functions looks quite nice but it requests the
iterables to be of the same length or otherwises will file with None
(most of time fails the function). Just wondering if there are already
enhancement work done with it?

I did some simple code but it will handle list without nesting only.
I am looking for examples that could hand input of "a = [2,3], b=4"
and "a=[1,[2,3],4], b=[5,[6,7,8],9,10]". That means if the nesting
structure is the same, enhanced map function will automatically extend
the shorter list using the last element. Or if the input is a constant
at the first point, then it feeds constant value to all other iterable
combinations.

Any tip is appreciated.
-Patrick.



def Add (x,y):
return x+y


def Bmap(function, *args):
num = 0
for iter in args[0:]:
if num < len(iter):
num = len(iter)

nlist=[]
for i in range(0,num,1):
fargs = []
for iter in args[0:]:
if len(iter) > i:
fargs.append(iter)
continue
fargs.append(iter[-1])

nlist.append(function(*fargs))
return nlist

if __name__ == '__main__':
a = [2,3]
b = [4,5,8]
print Bmap (Add, a, b)
 
S

Steven D'Aprano

Hi,

The build-in map functions looks quite nice but it requests the
iterables to be of the same length or otherwises will file with None
(most of time fails the function). Just wondering if there are already
enhancement work done with it?


That has been fixed in Python 3.1:
from operator import add
list(map(add, [1,2,3], [1,2,3,4,5]))
[2, 4, 6]

Starting from Python 2.3, the itertools module has had a function imap
with the same behaviour:
from operator import add
list(itertools.imap(add, [1,2,3], [1,2,3,4,5]))
[2, 4, 6]


I did some simple code but it will handle list without nesting only.

Surely that is a good thing. If you have a mix of nested and non-nested
data, that tells me your data is badly organized and needs to be fixed.

I am looking for examples that could hand input of "a = [2,3], b=4"

Using a small helper function:

import itertools

def make_iterable(obj):
try:
iter(obj)
except TypeError:
obj = itertools.cycle([obj])
return obj

def enhanced_map(func, *args):
args = map(make_iterable, args)
return list(itertools.imap(func, *args))


WARNING: this is dangerous. If none of the arguments are iterable, e.g.
you call enhanced_map(operator.add, 2, 3), this will happily loop forever
building a larger and larger list, until you run out of memory or kill
the Python process.

and "a=[1,[2,3],4], b=[5,[6,7,8],9,10]". That means if the nesting
structure is the same, enhanced map function will automatically extend
the shorter list using the last element.

It isn't clear what you want here. Are you expecting this enhanced map to
recursively drop down into each layer of sub-sequences? That is:

enhanced_map([1, [2,3, [4,5], 6], 7], [8, [7,6, [5,4], 3], 2])

should be the same as

map([1, 2, 3, 4, 5, 6, 7], [8, 7, 6, 5, 4, 3, 2])

or something different?


What do you expect to happen if the sub-sequences don't match up exactly?
E.g. a = [1, 2, [3, 4]]; b = [1, [2, 3], 4]

What do you expect to happen if the shorter list is empty?
E.g. a = [1, 2, [3, 4], 5]; b = [1, 2, [], 3]

This will get really messy fast. My advice is to forget about this as a
bad idea, and instead concentrate on making sure your data isn't so badly
arranged in the first place.
 
P

Patrick

Steven,

Thanks for the info of itertools. It is a great start for me. Overall,
I agree with you that it is really the user data needs to be sorted
out. However, novice users may need help on certain patterns such as
"a=[1,[2,3],4], b=[5,[6,7,8],9,10]". We could just draw our line
saying that similarly nested inputs could be adjusted even though the
members aren't exactly on one-to-one mapping and we won't getting any
deeper for complicated cases such as "a = [1, 2, [3, 4]]; b = [1, [2,
[3,4]], [4,5], 6]".
enhanced_map([1, [2,3, [4,5], 6], 7], [8, [7,6, [5,4], 3], 2])
should be the same as
map([1, 2, 3, 4, 5, 6, 7], [8, 7, 6, 5, 4, 3, 2])

I don't expect the drop. The original nested structure is very
important.

What do you expect to happen if the sub-sequences don't match up exactly?
E.g. a = [1, 2, [3, 4]]; b = [1, [2, 3], 4]

What do you expect to happen if the shorter list is empty?
E.g. a = [1, 2, [3, 4], 5]; b = [1, 2, [], 3]

There are modes called "shortest" and "longest" (and
"AllCombination"/"Cross" which is more complex).

For case a = [1, 2, [3, 4],4]; b = [1, [2, 3], 4,5]

shortest:
a will be adjusted to [1, [3, 4],4]
b will be adjusted to [1, [2, 3],4]

longest:
a will be adjusted to [1, 2,[3, 4],4,4]
b will be adjusted to [1, 1,[2, 3],4,5]

As I said previously, the enhance_map function will only handle
limited "unmatch" cases and the line will need to be drawn carefully.

Thanks
-Patrick.
 
S

Steven D'Aprano

Steven,

Thanks for the info of itertools. It is a great start for me. Overall, I
agree with you that it is really the user data needs to be sorted out.
However, novice users may need help on certain patterns such as
"a=[1,[2,3],4], b=[5,[6,7,8],9,10]".


You have misunderstood me. I'm not saying that you should force the users
to clean up the data (although of course you could do that), but that you
should do so before handing it to map.

Rather than putting all the smarts into enhanced_map, and having it
understand what to do with mismatched nested lists, deep nesting,
integers where you would expect a list, etc., you should write another
function that takes the user's data and adjusts it to some known,
consistent format, and then pass that on to map. Don't have one function
try to do too much.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top