Getting every possible combination in a list

Suppose I had something like this:

L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'...] for x in L1: input1= open('file_%s'%(x), 'r') file1= pickle.load(input1) for x in L1: input2= open('file_%s'%(x), 'r') file2= pickle.load(input2) 

and I wanted to get each combination of files without repeating already completed combinations (after cat_dog is done, do do do dog_cat again). Can I do it? My real list is in alphabetical order, if that matters.

+7
source share
6 answers

You can also do this as a generator:

 L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] tuples = [(x,y) for x in L1 for y in L1 if x != y] for entry in tuples: if (entry[1], entry[0]) in tuples: tuples.remove((entry[1],entry[0])) for pair in tuples: input1= open('file_%s'%(pair[0]), 'r') file1= pickle.load(input1) input2= open('file_%s'%(pair[1]), 'r') file2= pickle.load(input2) 

After the first loop, the contents of tuples are:

 ('cat', 'dog') ('cat', 'fish') ('cat', 'rabbit') ('cat', 'horse') ('cat', 'bird') ('cat', 'frog') ('cat', 'mouse') ('dog', 'fish') ('dog', 'rabbit') ('dog', 'horse') ('dog', 'bird') ('dog', 'frog') ('dog', 'mouse') ('fish', 'rabbit') ('fish', 'horse') ('fish', 'bird') ('fish', 'frog') ('fish', 'mouse') ('rabbit', 'horse') ('rabbit', 'bird') ('rabbit', 'frog') ('rabbit', 'mouse') ('horse', 'bird') ('horse', 'frog') ('horse', 'mouse') ('bird', 'frog') ('bird', 'mouse') ('frog', 'mouse') 
+5
source

In fact, what you are asking how to do is to create all combinations of two elements taken in the list of names (as opposed to all ) of a possible combination of them).

This means that you can use the itertools.combinations() built-in function to easily (and efficiently) generate the name pairs you want without repeating:

 L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] for pair in combinations(L1, 2): print(pair) input1 = open('file_%s' % pair[0], 'r') input2 = open('file_%s' % pair[1], 'r') 

Processed pairs:

 ('cat', 'dog') ('cat', 'fish') ('cat', 'rabbit') ('cat', 'horse') ('cat', 'bird') ('cat', 'frog') ('cat', 'mouse') ('dog', 'fish') ('dog', 'rabbit') ('dog', 'horse') ('dog', 'bird') ('dog', 'frog') ('dog', 'mouse') ('fish', 'rabbit') ('fish', 'horse') ('fish', 'bird') ('fish', 'frog') ('fish', 'mouse') ('rabbit', 'horse') ('rabbit', 'bird') ('rabbit', 'frog') ('rabbit', 'mouse') ('horse', 'bird') ('horse', 'frog') ('horse', 'mouse') ('bird', 'frog') ('bird', 'mouse') ('frog', 'mouse') 
+22
source

What about itertools.combinations ?

Usage example:

 >>> list(itertools.combinations([1, 2, 3, 4, 5, 6], 2)) [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6), (4, 5), (4, 6), (5, 6)] 

The first argument is iterable, the second is r , the length of the returned subsequences.

Then you can easily concatenate the results using a map or understanding:

 map(lambda x: x[0] + "_" + x[1], itertools.combinations(["cat", "dog", "fish"], 2))) 

x in lambda is an r dimensional tuple.

Result above:

 ['cat_dog', 'cat_fish', 'dog_fish'] 
+4
source
 import itertools import cPickle def unique_pairs(lst): return itertools.combinations(lst, 2) FNAME = "file_{0}".format def load_pickle(fname): with open(fname) as inf: return cPickle.load(inf) def naive_method(lst): # load each file every time it is requested for x,y in unique_pairs(lst): input1 = load_pickle(FNAME(x)) input2 = load_pickle(FNAME(y)) # do something with input1 and input2 def better_method(lst): # if you have enough memory for it! dat = [load_pickle(FNAME(i)) for i in lst] for x,y in unique_pairs(range(len(lst))): input1 = dat[x] input2 = dat[y] # do something with input1 and input2 
+3
source

There itertools that can perform combinations and permutations (you would like to use them). As far as I can tell, you cannot specify the output format, so you get "catdog" as the output, but on the doc page you get an idea of ​​how the combination function works, so you can adapt it to build what you need.

+2
source

An alternative to create a combination, without importing the module. Like @Nate's answer, but slightly less complex, creating a copy with individual elements and reducing it on the fly (instead of generating a list of pairs and shortening by searching the list):

 L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'] Laux = L1[:] pairs = [] for a in L1: Laux.remove(a) for b in Laux: pairs += [(a,b)] 
0
source

All Articles