在对象列表上考虑random.shuffle
(即不是像int这样的原始类型)。
我在谈论任何一般的对象;以下数字只是一个例子。
由于random.shuffle就地行动并返回None,这使得对该列表的切片或子集进行洗牌有点笨拙。 对于切片(或子集),有没有比采用切片(或深度复制),改组,然后用结果覆盖原始列表切片更好的方法?即如下:
import copy
import random
class SomeNumber(object): # just a stupid class to illustrate the point
def __init__(self, n):
self.n = n
def __repr__(self):
return str(self.n)
ll = [ SomeNumber(i) for i in range(6) ]
# [0, 1, 2, 3, 4, 5]
# Say we want to shuffle slice 2:end
#ld = copy.deepcopy(ll[2:])
ld = ll[2:]
# [2, 3, 4, 5]
random.shuffle(ld)
# [3, 2, 4, 5]
# ll didn't get shuffled though, so must overwrite the original slice...
ll[2:] = ld
# [0, 1, 5, 3, 4, 2]
del ld
还考虑更常见的情况,我可能想要传递一个布尔向量,其中哪些元素将包含在shuffle中。然后提取该子集,将其洗牌并重新插入。你能找到一个好习语吗?
PS @ReutSharabani建议如下:def partial_shuffle(lst, imin, imax):
lst[imin:imax] = sorted(lst[imin:imax], key=lambda x: random.random())
return lst
答案 0 :(得分:1)
如上所示:Why does random.shuffle return None?
#!/usr/bin/env python
import copy
import random
class SomeNumber(object): # just a stupid class to illustrate the point
def __init__(self, n):
self.n = n
def __repr__(self):
return str(self.n)
ll = [ SomeNumber(i) for i in range(6) ]
print ll
ll[2:] = sorted(ll[2:], key=lambda x: random.random())
print ll
它使用sorted
行为作为随机播放(根据随机键排序),但我不确定是否非常随意。
您可以创建一个shuffle函数来返回列表的混洗副本:
#!/usr/bin/env python
import random
# the function
def shuffle(ll, include_list=None):
if not include_list:
include_list = [True] * len(ll)
# tag the list (default: all, for use of slices) and shuffle
tagged_list = [x for x in zip(include_list, ll)]
shuffle_list = [x for x in tagged_list if x[0]]
random.shuffle(shuffle_list)
# re-insert to tagged list by false tags, enumerate indices changed
false_indices = sum(map(lambda x: [x[0]] if x[1][0] else [], enumerate(tagged_list)), [])
for shuffle_index, tagged_index in enumerate(false_indices):
tagged_list[tagged_index] = shuffle_list[shuffle_index]
# return only the values
return [x[1] for x in tagged_list]
# now use it whenever you want to shuffle something
l = [1, 2, 3, 4, 5]
print "shuffeled: %s" % shuffle(l)
# original list stays the same (not in-place)
print "original: %s" % l
# now to shuffle a part of a list you can:
print "shuffeled (2+): %s" % shuffle(l[2:])
# with a boolean filter list:
print "shuffle indices 0, 2, 4: %s " % shuffle(l, [True, False, True, False, True])