Take two random tuples from a list, such that all elements are different

Ziva Source

In Python3 I have a list of tuples as below

('A', object1)
('B', object5)
('B', object3)
('D', object2)
('E', object3)
('F', object1)
('G', object1)

I want to take two random elements from the tuple such that the first and second element of the first random tuple are different that the first and second element of the second random tuple. I.e., I can select from the above list ('A', object1) and ('B', object5), but I cannot select ('F', object1) and ('G', object1) or ('B', object5) and ('B', object3).

pythonpython-3.xrandom

Answers

answered 1 week ago Kasramvd #1

Here is one optimized way that chooses one item using random.sample and finding the first item that satisfies your condition:

In [116]: def rand_choos(arr):
     ...:     (f1, f2) = random.sample(arr, 1)[0]
     ...:     second = next((i, j) for i, j in arr if i != f1 and j != f2)
     ...:     return (f1, f2), second
     ...: 

In [117]: 

In [117]: rand_choos(lst)
Out[117]: (('B', 5), ('A', 1))

In [118]: rand_choos(lst)
Out[118]: (('D', 2), ('A', 1))

Also note that in this case you'll always get same second item for a random first item (while still different to the first one) because the order of the original list never changes. If this is an issue you can shuffle the array at the leading of the function to get completely different items (not all the time tho because it's just random):

In [149]: def rand_choos(arr):
     ...:     arr = arr[:] # this creates a copy for preventing the function to change the array globally
     ...:     random.shuffle(arr)
     ...:     (f1, f2) = random.sample(arr, 1)[0]
     ...:     second = next((i, j) for i, j in arr if i != f1 and j != f2)
     ...:     return (f1, f2), second
     ...: 

In [150]: rand_choos(lst)
Out[150]: (('B', 3), ('G', 1))

In [151]: rand_choos(lst)
Out[151]: (('B', 3), ('A', 1))

comments powered by Disqus