Search code examples
pythoncombinationspython-itertools

Generate all possible comparisons 3 v 3 in a group of 6


I have 6 samples and I would like to generate all possible 3v3 comparisons using python. So far I've managed to use the combinations function to generate all possible groups of 3. But I fail to generate the match comparisons (if I have CM26 in the first group I don't want to compare it against a group of 3 with it).

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = range(r)
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)
columns = {'CM19':1,'CM20':2,'CM21':3,'CM23':5,'CM25':7,'CM26':8}
for i in combinations(columns,3):
    print i

('CM26', 'CM19', 'CM25') ('CM26', 'CM19', 'CM23') ('CM26', 'CM19', 'CM20') ('CM26', 'CM19', 'CM21') ('CM26', 'CM25', 'CM23') ('CM26', 'CM25', 'CM20') ('CM26', 'CM25', 'CM21') ('CM26', 'CM23', 'CM20') ('CM26', 'CM23', 'CM21') ('CM26', 'CM20', 'CM21') ('CM19', 'CM25', 'CM23') ('CM19', 'CM25', 'CM20') ('CM19', 'CM25', 'CM21') ('CM19', 'CM23', 'CM20') ('CM19', 'CM23', 'CM21') ('CM19', 'CM20', 'CM21') ('CM25', 'CM23', 'CM20') ('CM25', 'CM23', 'CM21') ('CM25', 'CM20', 'CM21') ('CM23', 'CM20', 'CM21')

I would like to compare each group to the others but eliminating repetition.


Solution

  • Always pick a triple with the first element present, and use the complement of the set for the other triple.

    Here's code.

    import itertools
    
    def three_vs_three(xs):
        xset = set(xs)
        for i1, i2 in itertools.combinations(xs[1:], 2):
            triple = set([xs[0], i1, i2])
            yield sorted(triple), sorted(xset - triple)
    
    things = ['CM%d' % x for x in 19, 20, 21, 23, 25, 26]
    print list(three_vs_three(things))