What is the best way to join tuples?
Raymond Hettinger
vze4rx4y at verizon.net
Thu Nov 14 00:38:18 EST 2002
from __future__ import generators
def enumerate(seq):
i = 0
for elem in seq:
yield (i, elem)
i += 1
# I have two list of tuples, eg something like
wxyTuple = [(1,1,1), (1,1,2), (1,2,1), (2,2,1)] # tuples of (w,x,y)
xyzTuple = [(1,1,0), (1,2,1), (1,1,2)] # tuples of (x,y,z)
# and I want to join them together become (w,x,y,z), just like what we used
#to do with RDBMS by joining two tables together, with x,y acting as pivot.
#The result should be:
wxyzTuple = [(1,1,1,0),(1,1,1,2),(1,1,2,1),(1,2,1,-1),(2,2,1,-1)] # where -1
#is to indicate no match is found in xyzTuple
def tuplejoin(a, b, links):
""" Join lists of tuples with specified link fields.
Links is a list of field pairs showing the corresponding field
numbers for the join. For instance, the pair (2,4) indicates
that a[2] should correspond to b[4].
"""
akeys, bkeys = zip(*links)
bindexed = {}
for record in b:
keys = tuple(map(record.__getitem__, bkeys))
remainder = [] # fields not in the key, in the order found
for pos, element in enumerate(record):
if pos not in bkeys:
remainder.append(element)
bindexed.setdefault(keys, []).append(tuple(remainder))
bremsiz = len(remainder)
nomatch = (-1,) * bremsiz
result = []
for record in a:
keys = tuple(map(record.__getitem__, akeys))
matches = bindexed.get(keys, [nomatch])
for match in matches:
result.append(tuple(record) + match)
return result
print tuplejoin(wxyTuple, xyzTuple, [(1,0),(2,1)])
More information about the Python-list
mailing list