How to exclude generated random pairs that have been already used in a previous loop iteration?

Issue

I am trying to build a loop in which random pairs are generated given a list. Essentially, I want to create all combinations of random pairs using a loop without replacement. This is the logic with context:

import numpy as np

x=['apple','cherry','peach','banana']
count=len(x)
interaction=int(count-1) #possible count of matches for a given fruit

matched=[]
for i in range(interaction):
    pairs=np.random.choice(x, size=(int(count/2), 2), replace=False)
    matched.append(f'Run Number: {i+1}')
    matched.append(pairs.tolist())
          

print(matched)

['Run Number: 1', [['cherry', 'peach'], ['banana', 'apple']], 'Run Number: 2', [['banana', 'peach'], ['apple', 'cherry']], 'Run Number: 3', [['peach', 'cherry'], ['banana', 'apple']]]

The problem is that I want to restrict generating the same pairs. For example, in Run Number 1: we have the ‘cherry’, ‘peach’ pair. However, in Run Number 3, we have again ‘peach’, ‘cherry’ pair which is the same just inversed.

How can the subsequent iteration take into account the previous pairs saved in the matched list to generate new pairs based on what values are left over?

Solution

One possible solution that comes to mind is to use itertools.permutations to find all possible combinations of elements in a list, and then somehow filter out those "duplicate" elements – for example, you mentioned that (cherry, peach) and (peach, cherry) would not be considered unique as they both contain the same items essentially. So once we have possible pairs, we can filter out the result so we are left with the unique pairs in the end.

import itertools
from pprint import pprint

x = ['apple', 'cherry', 'peach', 'banana']

# Find the possible combinations of `x` in pairs of two elements each
possible_pairs = list(itertools.permutations(x, 2))

# That'll list you all possible permutations, even ones like
# (apple, peach) and (peach, apple). So, we'll want to filter
# these duplicates out.

# Note: I don't know if there's a better approach, this is just
# the first one that came to mind.

unique_pairs = []
for pair in possible_pairs:
    unique_pair = set(pair)
    if unique_pair not in unique_pairs:
        unique_pairs.append(unique_pair)

pprint(unique_pairs)

Output:

[{'apple', 'cherry'},
 {'peach', 'apple'},
 {'banana', 'apple'},
 {'peach', 'cherry'},
 {'banana', 'cherry'},
 {'banana', 'peach'}]

Update

Of course, there’s always an easier way to do things in Python, and in this case I was not aware there was a simpler approach. This answer here basically explained it to me. So now we can boil down the above logic to this:

unique_pairs = list(itertools.combinations(x, 2))

Which also gives the same result as the first attempt.

Answered By – rv.kvetch

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published