Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate every permutation of list elements pairs without repeating or inverted pairs

Tags:

python

I know this is similar to previous questions but there are enough differences in my request to merit a new question. I have a list of string elements.

>>> mainlist
['one', 'two', 'three', 'four', 'five']

I want to create a looped program that takes the first element and then pairs it with the remaining elements like so:

['one two', 'one three', 'one four', 'one five']

Notice it did not create the pair 'one one'

The next cycle should be:

['two three', 'two, four', 'two five']

Notice, again, it did not create 'two two' or even 'two one' as, for my purposes, this is equal to 'one two'.

and so on...

The nearest I've got is:

for primary in mainlist:
    for secondary in mainlist:
        if primary == secondary: print("skipping...")
        else: print(primary + " " + secondary)


>> skipping...
one two
one three
one four
one five
two one
skipping...
two three
two four
two five
three one
three two
skipping...
three four
three five
four one
four two
four three
skipping...
four five
five one
five two
five three
five four
skipping...

Based on the above you can see that this doesn't quite match what I'm after. Any help would be really appreciated - I'm sure there's an elegant solution out there somewhere.

like image 260
Beeman Avatar asked Apr 26 '16 07:04

Beeman


1 Answers

You want to use itertools.combinations:

In [1]: import itertools as it

In [2]:  mainlist = ['one', 'two', 'three', 'four', 'five']

In [3]: for a,b in it.combinations(mainlist, 2):
   ...:     print(a, b)
   ...:     
one two
one three
one four
one five
two three
two four
two five
three four
three five
four five

In the same way you could also create all possible triplets from the same by specifying 3 as second argument:

In [4]: for a,b,c in it.combinations(mainlist, 3):
   ...:     print(a, b,c)
   ...:     
one two three
one two four
one two five
one three four
one three five
one four five
two three four
two three five
two four five
three four five

If you want to produce also the pairs one one, two two etc. you should use combinations_with_replacement instead.


If you want to group together the pairs with the same first element you can use itertools.groupby:

In [1]: import itertools as it
   ...: mainlist = ['one', 'two', 'three', 'four', 'five']
   ...: 

In [2]: for key, group in it.groupby(it.combinations(mainlist, 2), key=lambda x:x[0]):
   ...:     print('key is', key)
   ...:     print('grouped elements', list(group))
key is one
grouped elements [('one', 'two'), ('one', 'three'), ('one', 'four'), ('one', 'five')]
key is two
grouped elements [('two', 'three'), ('two', 'four'), ('two', 'five')]
key is three
grouped elements [('three', 'four'), ('three', 'five')]
key is four
grouped elements [('four', 'five')]

Finally, if you want to write the loops explicitly you can use enumerate to keep track of your current index:

In [3]: for i, el in enumerate(mainlist):
   ...:     for el2 in mainlist[i+1:]:
   ...:         print(el, el2)
   ...:         
one two
one three
one four
one five
two three
two four
two five
three four
three five
four five

This is basically what combinations does, except that it works with arbitrary sizes (pairs, triplets etc)

like image 82
Bakuriu Avatar answered Nov 09 '22 23:11

Bakuriu