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