Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何随机排列对象列表的切片或子集?_Python_Shuffle_Slice_Sublist - Fatal编程技术网

Python 如何随机排列对象列表的切片或子集?

Python 如何随机排列对象列表的切片或子集?,python,shuffle,slice,sublist,Python,Shuffle,Slice,Sublist,考虑对象列表上的random.shuffle(即非int等基本类型)。 我说的是任何一般的对象;下面的数字只是一个例子 由于random.shuffle在适当的位置执行操作,并且不返回任何值,因此对该列表的某个片段或子集进行无序移动会有点笨拙。 对于一个片段(或子集),有没有比获取片段(或deepcopy)、洗牌它然后用结果覆盖原始列表片段更好的方法?i、 e.情况如下: import copy import random class SomeNumber(object): # just a

考虑对象列表上的
random.shuffle
(即非int等基本类型)。 我说的是任何一般的对象;下面的数字只是一个例子

由于random.shuffle在适当的位置执行操作,并且不返回任何值,因此对该列表的某个片段或子集进行无序移动会有点笨拙。 对于一个片段(或子集),有没有比获取片段(或deepcopy)、洗牌它然后用结果覆盖原始列表片段更好的方法?i、 e.情况如下:

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
再考虑一个更一般的情况,在这个情况下,我可能希望传递一个布尔向量,其中的元素将被包括在洗牌中。然后提取该子集,将其洗牌并重新插入。你能找到一个好的成语吗

PS@ReutSharabani建议如下:

def partial_shuffle(lst, imin, imax):
    lst[imin:imax] = sorted(lst[imin:imax], key=lambda x: random.random())
    return lst
如图所示:

它使用
sorted
作为洗牌(根据随机键排序),但是我不确定它是否真的是随机的

您可以创建一个混洗函数来返回列表的混洗副本:

#!/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])

如果您想洗牌原始列表的一部分,为什么要使用深度副本?你就不能切->洗牌->回写吗?@ReutSharabani:对。我更新了问题。但是有更好的成语吗?考虑更一般的情况下,我们通过布尔向量的洗牌/保持,在底部提到。最好的习惯用法是什么?如果你的意思是alecxe的回答提到可选的第二个arg
random.shuffle(x[,random])
,其中random是一个0参数函数,返回[0.0,1.0]中的随机浮点;(默认情况下,这是函数random()。使用该选项的代码肯定会更加笨拙。我的错,我指的是答案…出于某种原因,我认为它不是选定的答案。请参阅我发布的答案。因此:def partial_shuffle(lst,imin,imax):lst[imin:imax]=sorted(lst[imin:imax],key=lambda x:random.random())return lst您可以编写一个shuffle函数,使用
random.shuffle
返回被洗牌的列表,这可能就是我要做的…在洗牌之前一定要复制列表(您可以使用
l[:]
),这正是这个问题要求您做的;-)代码在哪里?我对你的代码忠贞不渝。如果你使用它一次,也许一个函数是一个多余的……我会把它添加进去……见我的答案的底部,我也要求一个统一的实现,同时考虑更一般的情况,在这里我想传递一个布尔向量,其中哪些元素将被包含在洗牌中。
#!/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])