python - 如何 random.shuffle 切片或对象列表的子集?

标签 python shuffle slice sublist

考虑对象列表上的 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

还要考虑更一般的情况,在这种情况下,我可能想要传递一个 bool 向量,其中包含哪些元素将包含在洗牌中。然后提取该子集,对其进行洗牌并重新插入。你能找到一个好的成语吗?

PS @ReutSharabani 建议如下:

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

最佳答案

见于: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充当随机播放(根据随机键排序),但我不确定是否真的是随机的.

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

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

关于python - 如何 random.shuffle 切片或对象列表的子集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27343932/

相关文章:

python - Python 3 中 float 的精确累积和

python - 使用 NSGA2 解决多目标问题时出现“TypeError”。来自 OpenMDAO 1.x 中的 pyopt-sparse

java - 在 Java 中打乱数组

jquery - 如何在页面刷新时随机化 <li> 元素?

c++ - 在 MacOS 10.9 (Mavericks) 上构建 Boost.Python 应用程序

python - 如何使用请求将 URL 中的日历选项作为 header 发送?

algorithm - 寻找有限的洗牌算法

通过使用值的 slice 作为带有 switch 语句的 case 来匹配一个值

struct - 如何创建不同类型的结构体数组的数组?

Python:如何在不创建范围的情况下计算范围的长度?