有效地配对列表的随机元素

时间:2019-05-15 19:57:08

标签: python list performance

我有一个n元素的列表,说:foo = ['a', 'b', 'c', 'd', 'e'] 我想随机配对此列表的元素以接收例如: bar = [['a', 'c'], ['b', 'e']],如果列表的长度不均匀,则最后一个元素将被丢弃。

现在,我有一个蛮力功能:

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)

这不是很有效。我也不喜欢就地更改列表。有任何更有效的方法吗?预先感谢。

4 个答案:

答案 0 :(得分:3)

我会说这是处理它的最Python方式:

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)

For循环:

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

给出的数字答案对我来说并没有超出范围。

答案 1 :(得分:1)

>>> import random
>>> foo = ['a', 'b', 'c', 'd', 'e']
>>> random.shuffle(foo)
>>> bar = list(zip(foo[::2], foo[1::2]))
>>> bar
[('e', 'd'), ('c', 'a')]

答案 2 :(得分:1)

尝试一下:

const fullName = `${lastName}, ${firstName}`

答案 3 :(得分:1)

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)