关于python:shuffling对象列表

Shuffling a list of objects

我在python中有一个对象列表,我想对它们进行无序排列。我以为我可以使用random.shuffle方法,但当列表中有对象时,这种方法似乎失败了。有没有一种方法可以改变物体或其他方法来绕过它?

1
2
3
4
5
6
7
8
9
10
import random

class a:
    foo ="bar"

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

print random.shuffle(b)

这会失败。


random.shuffle应该工作。下面是一个例子,其中对象是列表:

1
2
3
4
5
6
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在适当位置工作,不返回任何值。


正如你所了解到的,原地不动是问题所在。我也经常遇到问题,而且似乎经常忘记如何复制列表。以sample(a, len(a))为解决方案,以len(a)为样本量。参见https://docs.python.org/3.6/library/random.html random.sample了解python文档。

这里有一个使用random.sample()的简单版本,它将无序处理的结果作为新列表返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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


我也花了一些时间才弄到。但随机播放的文档非常清晰:

shuffle list x in place; return None.

所以你不应该这样做。相反,先是random.shuffle(b),然后是print b


1
2
3
4
5
6
7
8
9
#!/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]


如果你恰好已经使用了numpy(在科学和金融应用中非常流行),你就可以节省一笔进口。

1
2
3
import numpy as np    
np.random.shuffle(b)
print(b)

http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.shuffle.html


1
2
3
4
5
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

对我来说很好。确保设置随机方法。


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

1
2
3
4
5
6
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数组,则更简单:

1
2
3
4
5
import numpy as np

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

微处理器

我已经创建了小型实用程序包mpu,它具有consistent_shuffle功能:

1
2
3
4
5
6
7
8
9
10
11
12
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采用任意数量的参数。所以你也可以用它洗牌三个或更多的列表。


1
2
3
from random import random
my_list = range(10)
shuffled_list = sorted(my_list, key=lambda x: random())

对于某些要交换排序函数的应用程序,此选项可能很有用。


"print func(foo)"将在使用"foo"调用时打印"func"的返回值。"shuffle"的返回类型为"none",因为列表将在适当的位置进行修改,因此它不打印任何内容。解决办法:

1
2
3
4
5
# shuffle the list in place
random.shuffle(b)

# print it
print(b)

如果您更喜欢函数式编程风格,那么您可能希望使用以下包装器函数:

1
2
3
def myshuffle(ls):
    random.shuffle(ls)
    return ls


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

另一种选择是使用numpy.random.shuffle。如果您已经在使用numpy,这是比通用random.shuffle更好的方法。

numpy.random.shuffle(随机播放)

例子

1
2
>>> import numpy as np
>>> import random

使用random.shuffle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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]])


可以定义一个名为shuffled的函数(与sortsorted的意义相同)。

1
2
3
4
5
6
7
8
def shuffled(x):
    import random
    y = x[:]
    random.shuffle(y)
    return y

x = shuffled([1, 2, 3, 4])
print x

对于一个衬板,使用cx1〔0〕作为示例:

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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
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但是列表。


1
2
3
4
5
6
7
8
9
10
11
12
13
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


您可以构建一个函数,该函数将列表作为参数,并返回列表的无序版本:

1
2
3
4
5
6
7
8
9
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

你可以这样做:

1
2
3
4
5
>>> 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']

如果您想返回到两个列表,那么您可以将这个长列表拆分为两个。


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
""" 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


您可以使用随机播放或采样。两者都来自随机模块。

1
2
3
4
5
import random
def shuffle(arr1):
    n=len(arr1)
    b=random.sample(arr1,n)
    return b

1
2
3
4
import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1


1
2
3
4
5
6
7
8
import random
class a:
    foo ="bar"

a1 = a()
a2 = a()
b = [a1.foo,a2.foo]
random.shuffle(b)

计划:写下洗牌而不依靠图书馆做重举重。示例:从元素0开始浏览列表;为它找到一个新的随机位置,例如6,将0的值放在6中,将6的值放在0中。继续到元素1并重复这个过程,然后在列表的其余部分重复这个过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
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


洗牌过程是"带替换",因此每个项目的发生可能会改变!至少当列表中的项目也是列表时。

例如。,

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

之后,

1
random.shuffle(ml)

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


它很好用。我在这里尝试将函数作为列表对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    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"
"


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

它打印出来:Foo1-FoO2 FO3FoO2 FoO3 Foe1(最后一行的FOO顺序随机)