3 回答
TA贡献1895条经验 获得超7个赞
不是真的到位,但具有预期的结果:
import random
l = list(range(20))
lpart = l[:10]
random.shuffle(lpart)
l[:10] = lpart
print(l)
TA贡献1872条经验 获得超3个赞
修改列表 n-place 不会仅对列表的一部分起作用。您可以改为使用random.sample不替换的随机样本,然后切片分配:
k = 10
l[:k] = random.sample(l[:k], k=k)
print(l)
# [1, 7, 6, 0, 2, 3, 4, 9, 8, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
TA贡献1856条经验 获得超17个赞
可以使用Fisher-Yates shuffle从根本上重新实现random.shuffle()
以接受 afirst
和last
index 作为参数,例如:
import random
def valid_index(i, n):
assert(-n <= i < n)
return i % n
def shuffle(seq, first=0, last=-1, rand_int_gen=None):
n = len(seq)
first = valid_index(first, n)
last = valid_index(last, n)
# use Fisher-Yates shuffle (Durstenfeld method)
if callable(rand_int_gen):
for i in range(first, last):
j = rand_int_gen(i, last)
seq[i], seq[j] = seq[j], seq[i]
else:
getrandbits = random.getrandbits
for i in range(first, last + 1):
size = last - i + 1
j = getrandbits(size.bit_length()) % size + i
seq[i], seq[j] = seq[j], seq[i]
return seq
像这样使用:
l = list(range(20))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
random.seed(0) # just to show reproducible results
shuffle(l, 0, 9)
print(l)
# [6, 7, 2, 5, 8, 4, 9, 3, 0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
从时间上看,这实际上比random.shuffle()改组整个序列还要快几个百分点。
这本质上更快,因为它直接从中获取随机值,random.getrandbits()这是用于随机整数生成的最接近的方法random,其他方法,例如randint()并randrange()最终减少到这个。最后两个最终在内部使用_getrandbelow(),这可能会getrandbits()更频繁地调用必要的。
for k in range(1, 7):
n = 10 ** k
print(n)
%timeit l = list(range(n)); random.shuffle(l)
%timeit l = list(range(n)); shuffle(l)
print()
10
100000 loops, best of 3: 6.16 µs per loop
100000 loops, best of 3: 3.85 µs per loop
100
10000 loops, best of 3: 54.3 µs per loop
10000 loops, best of 3: 28 µs per loop
1000
1000 loops, best of 3: 585 µs per loop
1000 loops, best of 3: 341 µs per loop
10000
100 loops, best of 3: 6.01 ms per loop
100 loops, best of 3: 3.56 ms per loop
100000
10 loops, best of 3: 71.7 ms per loop
10 loops, best of 3: 44.1 ms per loop
1000000
1 loop, best of 3: 815 ms per loop
1 loop, best of 3: 582 ms per loop
正如@usr2564301 所指出的,这里也建议了这种方法。不幸的是,我认为没有更好的方法可以就地执行此操作。
添加回答
举报