860

我有一个对象列表,我想对它们进行洗牌。我以为我可以使用该random.shuffle方法,但是当列表是对象时,这似乎失败了。是否有洗牌对象的方法或解决此问题的其他方法?

import random

class A:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1, a2]

print(random.shuffle(b))

这将失败。

4

24 答案 24

1369

random.shuffle应该管用。这是一个示例,其中对象是列表:

from random import shuffle
x = [[i] for i in range(10)]
shuffle(x)

# print(x)  gives  [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]
# of course your results will vary

请注意,shuffle 可以在原地工作,并返回 None。

于 2009-06-10T17:03:37.447 回答
129

正如您所了解的,就地改组是问题所在。我也经常遇到问题,而且似乎也经常忘记如何复制列表。使用sample(a, len(a))是解决方案,使用len(a)作为样本大小。有关 Python 文档,请参阅https://docs.python.org/3.6/library/random.html#random.sample

这是一个简单的版本,它使用random.sample()将洗牌结果作为新列表返回。

import random

a = range(5)
b = random.sample(a, len(a))
print a, b, "two list same:", a == b
# print: [0, 1, 2, 3, 4] [2, 1, 3, 4, 0] two list same: False

# The function sample allows no duplicates.
# Result can be smaller but not larger than the input.
a = range(555)
b = random.sample(a, len(a))
print "no duplicates:", a == list(set(b))

try:
    random.sample(a, len(a) + 1)
except ValueError as e:
    print "Nope!", e

# print: no duplicates: True
# print: Nope! sample larger than population
于 2012-10-19T16:50:08.050 回答
74

我也花了一些时间才明白这一点。但是 shuffle 的文档非常清楚:

随机播放列表 x 返回无。

所以你不应该print(random.shuffle(b))。而是做random.shuffle(b)然后print(b)

于 2014-11-21T14:49:30.740 回答
46
#!/usr/bin/python3

import random

s=list(range(5))
random.shuffle(s) # << shuffle before print or assignment
print(s)

# print: [2, 4, 1, 3, 0]
于 2010-12-04T12:46:10.337 回答
34

如果您碰巧已经在使用numpy(在科学和金融应用中非常流行),您可以为自己节省一个导入。

import numpy as np    
np.random.shuffle(b)
print(b)

https://numpy.org/doc/stable/reference/random/generated/numpy.random.shuffle.html

于 2015-02-28T02:35:34.740 回答
25
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

这对我来说可以。确保设置随机方法。

于 2009-06-10T17:04:16.930 回答
17

如果您有多个列表,您可能需要先定义排列(打乱列表/重新排列列表中项目的方式),然后将其应用于所有列表:

import random

perm = list(range(len(list_one)))
random.shuffle(perm)
list_one = [list_one[index] for index in perm]
list_two = [list_two[index] for index in perm]

Numpy / Scipy

如果您的列表是 numpy 数组,则更简单:

import numpy as np

perm = np.random.permutation(len(list_one))
list_one = list_one[perm]
list_two = list_two[perm]

微处理器

我创建了mpu具有以下consistent_shuffle功能的小型实用程序包:

import mpu

# Necessary if you want consistent results
import random
random.seed(8)

# Define example lists
list_one = [1,2,3]
list_two = ['a', 'b', 'c']

# Call the function
list_one, list_two = mpu.consistent_shuffle(list_one, list_two)

请注意,mpu.consistent_shuffle它采用任意数量的参数。因此,您还可以使用它随机播放三个或更多列表。

于 2017-02-05T16:15:29.630 回答
12

对于单行,使用random.sample(list_to_be_shuffled, length_of_the_list)示例:

import random
random.sample(list(range(10)), 10)

输出:[2, 9, 7, 8, 3, 0, 4, 1, 6, 5]

于 2018-09-17T15:59:05.203 回答
10
from random import random
my_list = range(10)
shuffled_list = sorted(my_list, key=lambda x: random())

此替代方法可能对您想要交换排序功能的某些应用程序有用。

于 2016-05-06T00:04:46.690 回答
10

在某些情况下,当使用 numpy 数组时,会在数组中使用random.shuffle创建的重复数据。

另一种方法是使用numpy.random.shuffle. 如果您已经在使用 numpy,那么这是通用的首选方法random.shuffle

numpy.random.shuffle

例子

>>> import numpy as np
>>> import random

使用random.shuffle

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [1, 2, 3],
       [4, 5, 6]])

使用numpy.random.shuffle

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> np.random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [7, 8, 9],
       [4, 5, 6]])
于 2016-12-19T17:01:26.610 回答
7

当使用 'foo' 调用时,'print func(foo)' 将打印 'func' 的返回值。然而,'shuffle' 将 None 作为其返回类型,因为列表将被修改到位,因此它不打印任何内容。解决方法:

# shuffle the list in place 
random.shuffle(b)

# print it
print(b)

如果您更喜欢函数式编程风格,则可能需要制作以下包装函数:

def myshuffle(ls):
    random.shuffle(ls)
    return ls
于 2013-05-24T14:59:33.330 回答
5

可以定义一个名为shuffled(与sortvs相同sorted)的函数

def shuffled(x):
    import random
    y = x[:]
    random.shuffle(y)
    return y

x = shuffled([1, 2, 3, 4])
print x
于 2016-05-06T00:48:25.397 回答
3
import random

class a:
    foo = "bar"

a1 = a()
a2 = a()
a3 = a()
a4 = a()
b = [a1,a2,a3,a4]

random.shuffle(b)
print(b)

shuffle 就位,所以不要打印结果,即None,而是列表。

于 2018-06-14T06:08:18.257 回答
2

您可以使用 shuffle 或 sample 。两者都来自随机模块。

import random
def shuffle(arr1):
    n=len(arr1)
    b=random.sample(arr1,n)
    return b

或者

import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1
于 2018-09-02T05:05:47.607 回答
1

你可以这样做:

>>> A = ['r','a','n','d','o','m']
>>> B = [1,2,3,4,5,6]
>>> import random
>>> random.sample(A+B, len(A+B))
[3, 'r', 4, 'n', 6, 5, 'm', 2, 1, 'a', 'o', 'd']

如果你想回到两个列表,然后将这个长列表分成两个。

于 2014-05-17T11:53:48.230 回答
1

您可以构建一个将列表作为参数并返回列表的打乱版本的函数:

from random import *

def listshuffler(inputlist):
    for i in range(len(inputlist)):
        swap = randint(0,len(inputlist)-1)
        temp = inputlist[swap]
        inputlist[swap] = inputlist[i]
        inputlist[i] = temp
    return inputlist
于 2017-08-09T16:46:57.297 回答
1
""" to shuffle random, set random= True """

def shuffle(x,random=False):
     shuffled = []
     ma = x
     if random == True:
         rando = [ma[i] for i in np.random.randint(0,len(ma),len(ma))]
         return rando
     if random == False:
          for i in range(len(ma)):
          ave = len(ma)//3
          if i < ave:
             shuffled.append(ma[i+ave])
          else:
             shuffled.append(ma[i-ave])    
     return shuffled
于 2018-03-28T09:34:51.297 回答
1

如果您需要就地改组和操作种子的能力,此代码段将有所帮助:

from random import randint

a = ['hi','world','cat','dog']
print(sorted(a, key=lambda _: randint(0, 1)))

请记住,“洗牌”是按随机键排序的。

于 2021-05-19T07:39:19.953 回答
0

确保您没有将源文件命名为 random.py,并且您的工作目录中没有名为 random.pyc 的文件。这可能会导致您的程序尝试导入本地 random.py 文件而不是 pythons 随机模块.

于 2014-02-11T16:59:01.817 回答
0
def shuffle(_list):
    if not _list == []:
        import random
        list2 = []
        while _list != []:
            card = random.choice(_list)
            _list.remove(card)
            list2.append(card)
        while list2 != []:
            card1 = list2[0]
            list2.remove(card1)
            _list.append(card1)
        return _list
于 2017-05-29T14:49:39.867 回答
0
import random
class a:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1.foo,a2.foo]
random.shuffle(b)
于 2018-09-05T03:26:13.997 回答
-1

洗牌过程是“有替换”,所以每个项目的出现可能会改变!至少当列表中的项目也是列表时。

例如,

ml = [[0], [1]] * 10

后,

random.shuffle(ml)

[0] 的数量可能是 9 或 8,但不完全是 10。

于 2016-04-25T20:18:27.880 回答
-1

计划:写出洗牌而不依赖图书馆来做繁重的工作。示例:从元素 0 开始遍历列表;为它找到一个新的随机位置,比如 6,将 0 的值放入 6 中,将 6 的值放入 0 中。移动到元素 1 并重复此过程,依此类推,直到列表的其余部分

import random
iteration = random.randint(2, 100)
temp_var = 0
while iteration > 0:

    for i in range(1, len(my_list)): # have to use range with len()
        for j in range(1, len(my_list) - i):
            # Using temp_var as my place holder so I don't lose values
            temp_var = my_list[i]
            my_list[i] = my_list[j]
            my_list[j] = temp_var

        iteration -= 1
于 2016-11-12T20:28:31.907 回答
-2

它工作正常。我在这里尝试使用作为列表对象的函数:

    from random import shuffle

    def foo1():
        print "foo1",

    def foo2():
        print "foo2",

    def foo3():
        print "foo3",

    A=[foo1,foo2,foo3]

    for x in A:
        x()

    print "\r"

    shuffle(A)
    for y in A:
        y()

它打印出: foo1 foo2 foo3 foo2 foo3 foo1 (最后一行中的 foos 具有随机顺序)

于 2014-06-28T06:11:44.590 回答