0

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?

TaSa85920
  • 7
  • 2

2 Answers2

1

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.

rv.kvetch
  • 9,940
  • 3
  • 24
  • 53
0

I've done this kind of thing in java and what I did was to create another list to hold all the items added then check it before adding new one. That way I only add items that wasnt added and once the loop ends I clear the list to free memory.

In python you can use "in" statement as follows:

   array = [ a,b,c]
   hasitem = a in array
   print(hasitem)
   #this will display true

So in your case now you need to loop through pairs to get each item and check against list storing your added items then add only the ones that is not in the list.

Edited Example:

     x=['apple','cherry','peach','banana']
     c=[]
    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)
              if pairs.tolist()[i] not in c:
                    matched.append(f'Run Number: {i+1}')
                    matched.append(pairs.tolist()[i])
                    c.append(pairs.tolist()[i])
Chukwu Remijius
  • 323
  • 1
  • 14