[perl-python] exercise: partition a list by equivalence

Reinhold Birkenfeld reinhold-birkenfeld-nospam at wolke7.net
Sun Feb 20 08:41:48 EST 2005


Reinhold Birkenfeld wrote:

> My solution (which may not be the fastest or most effective, but till
> now is the shortest <wink> and it works):
> 
> def merge(pairings):
>     sets = {}
>     for x1, x2 in pairings:
>         newset = (sets.get(x1, frozenset([x1]))
>                   | sets.get(x2, frozenset([x2])))
>         for i in newset:
>             sets[i] = newset
> 
>     return [list(aset) for aset in set(sets.itervalues())]

A recursive solution (around twice as fast as the above, though very
slow still...)

def merge_rb2(pairings):
    def merge(sets):
        res_sets = []
        for tset in sets:
            for item in tset:
                for rset in res_sets:
                    if item in rset:
                        rset.update(item for item in tset)
                        break
                else:
                    continue
                break
            else:
                res_sets.append(set(tset))
        if len(res_sets) == len(sets):
            return res_sets
        else:
            return merge(res_sets)

    return [list(s) for s in merge([set(pair) for pair in pairings])]

Another one:

def merge_rb3(pairings):
    dic = {}
    for x1, x2 in pairings:
        dic.setdefault(x1, []).append(x2)
        dic.setdefault(x2, []).append(x1)

    def red(k, l):
        l.append(k)
        sub = dic[k]
        for i in dic[k]:
            if i not in l:
                red(i, l)
        del dic[k]

    res = []
    while len(dic):
        rl = []
        red(iter(dic).next(), rl)
        res.append(rl)

    return res

Reinhold



More information about the Python-list mailing list