import psyco
# function bound below.
old_map = map
def mymap4(func, *seqs):
""" supports normal map functionality. but is slower.
"""
if func is None:
if len(seqs) == 1:
#return list(seqs[0])
return seqs[0]
else:
#return list(apply(zip,seqs))
# Need a non truncating zip :)
# instead we make the None a function.
func = lambda *x:x
len_seqs = len(seqs)
if len_seqs == 1:
return [func(x) for x in seqs[0]]
return_seq = []
return_seq_append = return_seq.append
# find the biggest length.
biggest_length = 0
first_length = -1
different_sizes = 0
seqs_lengths = []
for seq in seqs:
length = len(seq)
if first_length == -1:
first_length = length
if length != first_length:
different_sizes = 1
seqs_lengths.append([seq,length])
if length > biggest_length:
biggest_length = length
# if the sequences are different lengths, make some new ones
# with Nones appended to make them the same size.
if different_sizes:
new_seqs = []
new_seqs_append =new_seqs.append
for seq, length in seqs_lengths:
new_bit = list(seq)
new_bit_append = new_bit.append
for i in xrange(biggest_length - length):
new_bit_append(None)
new_seqs_append(new_bit)
seqs = new_seqs
if len_seqs == 2:
# this case is faster than even the old map.
seq_0 = seqs[0]
seq_1 = seqs[1]
for i in xrange(biggest_length):
return_seq_append( func(seq_0[i], seq_1[i]) )
else:
# this case is about 2.5 times slower than the special case above.
# which is about twice as slow as normal map.
new_bit = []
for x in xrange(len_seqs):
new_bit.append(None)
for i in xrange(biggest_length):
for seqi in xrange(len_seqs):
new_bit[seqi] = seqs[seqi][i]
return_seq_append( apply(func,new_bit) )
return return_seq
def mymap5(func, *seqs):
""" supports normal map functionality.
uses old_map for cases where it's faster.
"""
#func = args[0]
#seqs = args[1:]
if func is None or len(seqs) != 1:
return old_map(func, *seqs)
return_seq = []
return_seq_append = return_seq.append
for item in seqs[0]:
return_seq_append(func(item))
return return_seq
# number 6 is from pypy.
def mymap6(function, *collections):
"""does 3 separate things, hence this enormous docstring.
1. if function is None, return a list of tuples, each with one
item from each collection. If the collections have different
lengths, shorter ones are padded with None.
2. if function is not None, and there is only one collection,
apply function to every item in the collection and return a
list of the results.
3. if function is not None, and there are several collections,
repeatedly call the function with one argument from each
collection. If the collections have different lengths,
shorter ones are padded with None
"""
if len(collections) == 0:
raise TypeError, "map() requires at least one sequence"
elif len(collections) == 1:
#it's the most common case, so make it faster
if function is None:
return collections[0]
else:
return [function(x) for x in collections[0]]
else:
res = []
idx = 0
while 1:
cont = 0 #is any collection not empty?
args = []
for collection in collections:
try:
elem = collection[idx]
cont = cont + 1
except IndexError:
elem = None
args.append(elem)
if cont:
if function is None:
res.append(tuple(args))
else:
res.append(function(*args))
else:
return res
idx = idx + 1
psyco.bind(mymap4)
psyco.bind(mymap5)
psyco.bind(mymap6)