Я бы сказал, что это самый питонический способ справиться с этим:
foo = ['a', 'b', 'c', 'd', 'e', 'f']
random.shuffle(foo)
length = len(foo)//2
result = list(zip(foo[:length], foo[length:]))
Zip объединит элементы в одном и том же индексе нескольких списков и остановится, когда в одном списке закончатся элементы. Итак, вы собираетесь перетасовать список и взять первую и вторую половину списка, а затем комбинировать их поэлементно до тех пор, пока у более короткого не останется элементов.
Изменить: вы сказали, что вы заинтересованы в исполнении различных способов обработки. Я сделал функцию для каждого из уникальных ответов здесь и рассчитал их время:
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[0]), foo.pop(pair_idxs[1] - 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:])
почтовый индекс без списка:
%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)
Ответ на вопрос, который мне дали, не закончился.