Efficiently pair random elements of list

2024/9/22 14:20:30

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[0]), foo.pop(pair_idxs[1] - 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.

Answer

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)//2return 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 resultdef 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[0]), foo.pop(pair_idxs[1] - 1)]el_pairs.append(el_pair)return el_pairsdef f(foo):random.shuffle(foo)length = len(foo)//2return 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)

Zip:

%timeit a(foo)
4.36 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

List comprehension:

%timeit b(foo)
4.38 µs ± 22.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

For loop:

%timeit d(foo)
812 ns ± 5.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Original:

%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.

https://en.xdnf.cn/q/119124.html

Related Q&A

ALL permutations of a list with repetition but not doubles

I have seen similar but not the same: here. I definitely want the permutations, not combinations, of all list elements. Mine is different because itertools permutation of a,b,c returns abc but not aba …

NameError: name current_portfolio is not defined

I am getting NameError: name current_portfolio is not defineddef initialize(context): context.sym = symbol(xxx) context.i = 0def handle_data(context, data):context.i += 1 if context.i < 60:returnsma…

Scrape an Ajax form with .submit() with Python and Selenium

I am trying to get the link from a web page. The web page sends the request using javascript, then the server sends a response which goes directly to download a PDF. This new PDF is automatically downl…

How to process break an array in Python?

I would like to use a double array. But I still fail to do it. This what I did. Folder = "D:\folder" Name = [gadfg5, 546sfdgh] Ver = [None, hhdt5463]for dn in Name :for dr in Ver :if dr is No…

Why am I getting replacement index 1 out of range for positional args tuple error

I keep getting this error: Replacement index 1 out of range for positional args tuple on this line of code: print("{1}, {2}, {3}, {4}".format(question[3]), question[4], question[5], question[…

Python: Find keywords in a text file from another text file

Take this invoice.txt for exampleInvoice NumberINV-3337Order Number12345Invoice DateJanuary 25, 2016Due DateJanuary 31, 2016And this is what dict.txt looks like:Invoice DateInvoice NumberDue DateOrder …

How to split a list into chucks of different sizes specified by another list? [duplicate]

This question already has answers here:How to Split or break a Python list into Unequal chunks, with specified chunk sizes(3 answers)Closed 4 years ago.I have an array I am trying to split into chunks …

Python Sum of digits in a string function

My function needs to take in a sentence and return the sum of the numbers inside. Any advice?def sumOfDigits(sentence):sumof=0for x in sentence:if sentence.isdigit(x)== True:sumof+=int(x)return sumof

How to select columns using dynamic select query using window function

I have sample input dataframe as below, but the value (clm starting with m) columns can be n number. customer_id|month_id|m1 |m2 |m3 .......m_n 1001 | 01 |10 |20 1002 | 01 |20…

Downloading Books from website with python

Im downloading books from the website, and almost my code runs smoothly, but when I try to open the pdf Book on my PC. An error generated by Adobe Acrobat Reader that this is not supported file type.He…