Efficiently pair random elements of list
I have a list of
n elements say:
foo = ['a', 'b', 'c', 'd', 'e']
I would like to randomly pair elements of this list to receive for example:
bar = [['a', 'c'], ['b', 'e']] where the last element will be discarded if the length of the list is not even.
Right now, I have a brute force function:
def rnd_pair(foo): while len(foo) > 1: pair_idxs = np.sort(np.random.choice(range(len(foo)), 2, replace=False)) el_pair = [foo.pop(pair_idxs), foo.pop(pair_idxs - 1)] el_pairs.append(el_pair)
This is not really efficient. Also I don't like changing the list in-place. Any ideas on a more efficient way? Thanks in advance.
I would say this is the most pythonic way of handling it:
foo = ['a', 'b', 'c', 'd', 'e', 'f'] random.shuffle(foo) length = len(foo)//2 result = list(zip(foo[:length], foo[length:]))
Zip will combine the elements at the same index of multiple lists and stop when one list runs out of elements. So you're going to to shuffle the list, and take the first and 2nd half of the list, then combine them element wise until the shorter one runs out of elements.
Edit: you said you were interested in the performance of different ways of handling it. I made a function for each of the unique answers here and timed them:
def a(foo): random.shuffle(foo) length = len(foo)//2 return list(zip(foo[:length], foo[length:])) def b(foo): random.shuffle(foo) return [[foo[i], foo[i+1]] for i in range(0, len(foo)-(len(foo)%2), 2)] def c(foo): np.random.shuffle(foo) return foo[:len(foo)-(len(foo)%2)].reshape(2,-1) def d(foo): result =  for i in range(1, len(foo), 2): result.append([foo[i-1], foo[i]]) return result def e(foo): el_pairs =  while len(foo) > 1: pair_idxs = np.sort(np.random.choice(range(len(foo)), 2, replace=False)) el_pair = [foo.pop(pair_idxs), foo.pop(pair_idxs - 1)] el_pairs.append(el_pair) return el_pairs def f(foo): random.shuffle(foo) length = len(foo)//2 return zip(foo[:length], foo[length:])
Zip without list:
%timeit f(foo) 3.96 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit a(foo) 4.36 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit b(foo) 4.38 µs ± 22.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit d(foo) 812 ns ± 5.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit e(foo) 154 ns ± 1.11 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
The numpy answer given didn't run out of box for me.
Selecting Random Elements from a List Without Repetition, Selecting Random Elements from a List Without Repetition Credit: Iuri Wickert, Duncan Grisby, Steve Holden, Alex Martelli Problem You need to consume,� Method #1 : Using list comprehension List comprehension can be used to print the pairs by accessing current and next element in the list and then printing the same. Care has to be taken while pairing the last element with the first one to form a cyclic pair.
>>> import random >>> foo = ['a', 'b', 'c', 'd', 'e'] >>> random.shuffle(foo) >>> bar = list(zip(foo[::2], foo[1::2])) >>> bar [('e', 'd'), ('c', 'a')]
How to create random, nonrepetitive pairs from a list in Python, pairs = list(itertools.combinations(numbers, 2)). # Randomly shuffle these pairs. random� To get random elements from sequence objects such as lists ( list ), tuples ( tuple ), strings ( str) in Python, use choice (), sample (), choices () of the random module. choice () returns one random element, and sample () and choices () return a list of multiple random elements. sample () is used for random sampling without replacement, and choices () is used for random sampling with replacement.
from random import shuffle foo = ['a', 'b', 'c', 'd', 'e'] shuffle(foo) result =  for i in range(1, len(foo), 2): result.append([foo[i-1], foo[i]]) print(result)
Python random.choice() to choose random element from list, String , Python random.choice() function to select random item from a List and Set Pick a random value from multiple lists; Choose a random element from a Faster and Efficient way to generate random boolean in Python random.choice(list( weight_dict)) print ("Random key-value pair from dictonary is ", key,� Let see how to use the random.choice () function to select random key-value pair from a Python dictionary. The random.choice () function of a random module doesn’t accept a dictionary, you need to convert a dictionary into a list before passing it to randonm.choice () function. Let see the example of how to choose dict keys randomly.
import random import string def random_pairs(x): random.shuffle(x) return zip(*(2 * [iter(x)])) # Shuffling in place. array = list(string.lowercase) # a-z print list(random_pairs(array)) # Not Shuffling in place. array = list(string.uppercase) # A-Z pairs = random_pairs(range(len(array))) print map(lambda pair: map (lambda i: array[i], pair), pairs)
Python random.sample() to choose multiple items from any sequence, Python random.sample() function to choose multiple Items from List, Set and Dictionary The random.sample() returns a list of unique elements chosen generate a list of unique random numbers because it is fast, memory-efficient, Yes, it is possible to select a random key-value pair from the dictionary. Efficient approach: First find out the number of unique elements in an array. Let the number of unique elements be x. Then, the number of unique pairs would be x2. This is because each unique element can form a pair with every other unique element including itself.
Python, Shuffling a sequence of numbers have always been an useful utility and the question that has Swap arr[i] with the element at random index. Efficiency Ambiguity Distinguishing A List of One Element from The Element Itself A simple string like foo is indistinguishable from a list of length one containing the list element foo. set x [list a [list b] c] set y [list a b c] set x => a b c set y => a b c Keyed Lists
If your list itself contains repeated or duplicate elements, then random.sample () can pick repeated items because each occurrence is a possible selection in the sample. I.e., The random.sample () can pick the repeated items from the specified list if the unique members are less than a sampling size.
The total number of pairs is just m* (m-1)/2. (I.e., the sum of the numbers from 1 to m-1.) So we could generate n random integers in the range [1,m* (m-1)/2]. Randperm does this nicely. (Older matlab releases do not allow the second argument to randperm.) k = randperm(m/2*(m-1),n);
- Possible duplicate of Creating random pairs from lists
- I was more interested in the performance part. I will edit the title. Thanks for showing the other question.
- Don't forget you can upvote all answers here if you found them useful :) @oezguensi
- dont get the upvote though? it isn't a duplicate regarding the performance side.
- I was also testing the speed of the answer and can confirm. Thanks for the effort
- For a seq of length 1e4, running 10 times faster using numpy, compared with d