객체 목록 섞기


770

객체 목록이 있고 섞고 싶습니다. 나는이 random.shuffle방법을 사용할 수 있다고 생각 했지만 목록이 객체 일 때 실패하는 것 같습니다. 객체를 섞는 방법이 나이 주위에 다른 방법이 있습니까?

import random

class A:
    foo = "bar"

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

print(random.shuffle(b))

실패합니다.


6
어떻게 실패하는지 예를 들어 줄 수 있습니까? random.shuffle은 목록의 객체 유형에 따라 달라지지 않습니다.
bayer

3
>>> a1 = a () >>> a2 = a () >>> b = [a1, a2] >>> b [<__ main __. a 0xb7df9e6c의 인스턴스>, <__ main __. a 0xb7df9e2c의 인스턴스>]> >> print random.shuffle (b) 없음
utdiscant

135
아래에 언급 된대로 random.shuffle은 새로운 셔플 목록을 반환하지 않습니다. 목록을 순서대로 섞습니다. 따라서 "print random.shuffle (b)"라고 말하지 말고 한 줄에 셔플을하고 다음 줄에 b를 인쇄해야합니다.
Eli

numpy 배열을 섞으려고하면 아래의 대답을 참조하십시오.
Gordon Bean

1
원래 배열을 변경하지 않고 새로운 셔플 배열을 반환하는 옵션이 있습니까?
Charlie Parker

답변:


1241

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

셔플은 제자리 에서 작동 하며 없음을 반환합니다.


1
@seokhoonlee 어느 쪽도. 가능한 경우 OS의 실제 무작위 소스에 의해 시드되는 pseduo-random number generator입니다. 암호화를 제외하고는 모두 "충분한"무작위입니다. 이것은 random모듈의 문서 에 자세히 설명되어 있습니다 .
dimo414

2
새로운 목록을 위해 clone 사용
Mohammad Mahdi KouchakYazdi

8
원래 배열을 변경하지 않고 새로운 셔플 배열을 반환하는 옵션이 있습니까?
Charlie Parker

5
@CharlieParker : 내가 아는 것은 아닙니다. random.sample(x, len(x))사본을 사용 하거나 복사 할 수 있습니다 shuffle. 들어 list.sort있는 지금 거기에, 비슷한 문제를 가지고 list.sorted있지만 대해 유사한 변종이 아니다 shuffle.
tom10

6
암호 보안 임의성에 대해서는 @seokhonlee를 from random import SystemRandom대신 사용하십시오. cryptorand = SystemRandom()행 3을 추가 하고cryptorand.shuffle(x)
browly로

115

내부 셔플 링을 배운대로 문제가 발생했습니다. 나는 또한 자주 문제가 있으며 종종 목록을 복사하는 방법을 잊어 버리는 것 같습니다. 사용 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

원래 배열을 변경하지 않고 새로운 셔플 배열을 반환하는 옵션이 있습니까?
Charlie Parker

@CharlieParker : old = [1,2,3,4,5]; new = list(old); random.shuffle(new); print(old); print(new)(줄 바꿈으로 대체)
fjsj

old[:]또한 목록을 위해 얕은 사본을 할 수 old있습니다.
Xiao

sample()데이터 분석 프로토 타이핑에 특히 유용합니다. sample(data, 2)파이프 라인의 글루 코드를 설정 한 다음 최대 단계적으로 "확대"합니다 len(data).
Katrin Leinweber

58

그것을 얻는 데 시간이 걸렸습니다. 그러나 셔플에 대한 문서는 매우 명확합니다.

목록 x 를 섞으십시오 . None을 반환합니다.

따라서해서는 안됩니다 print(random.shuffle(b)). 대신 할 random.shuffle(b)다음과 print(b).


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

31

이미 numpy를 사용하고 있다면 (과학 및 금융 응용 프로그램에 매우 인기가 있음) 수입을 절약 할 수 있습니다.

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

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


이 답변에 대해 내가 좋아하는 것은 임의의 시드를 numpy로 제어 할 수 있다는 것입니다. 무작위 모듈에 그렇게 할 수있는 방법이 있지만 지금 당장은 분명하지 않습니다 ... 더 읽을 필요가 있음을 의미합니다.
VanBantam

25
>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

그것은 나를 위해 잘 작동합니다. 무작위 방법을 설정하십시오.


여전히 작동하지 않습니다. 편집 된 질문에서 예제 코드를 참조하십시오.
utdiscant 2016 년

4
두 번째 매개 변수의 기본값은 random.random입니다. 그것을 버리는 것이 완벽하게 안전합니다.
cbare

3
@alvas random.shuffle (a)는 아무 것도 반환하지 않습니다. 즉 None을 반환합니다. 따라서 반환 값이 아닌지 확인해야합니다.
sonus21

15

목록이 여러 개인 경우 순열을 정의하고 (목록을 섞거나 목록의 항목을 다시 정렬하는 방법) 먼저 모든 목록에 적용 할 수 있습니다.

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 배열이면 더 간단합니다.

import numpy as np

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

mpu

함수 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인수의 임의의 수를합니다. 따라서 세 개 이상의 목록을 섞을 수도 있습니다.


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

이 대안은 주문 기능을 교체하려는 일부 응용 프로그램에 유용 할 수 있습니다.


또한, 덕분에 sorted이것은 기능 셔플입니다 (당신이 그런 종류의 일에 있다면).
Inaimathi

1
Timsort의 안정성으로 인해 값을 임의로 임의로 분배하는 것은 아닙니다. (같은 키를 가진 값은 원래 순서대로 남아 있습니다.) 편집 : 64 비트 부동 소수점과의 충돌 위험이 매우 적기 때문에 중요하지 않다고 생각합니다.
Mateen Ulhaq

10

numpy 배열을 사용하는 경우 배열에서 random.shuffle생성 된 중복 데이터를 사용하는 경우가 있습니다.

대안은을 사용하는 것 numpy.random.shuffle입니다. 이미 numpy를 사용하고 있다면 generic보다 선호되는 방법 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]])

1
또한 numpy.random.permutation관심을 가질만한
Gordon Bean

random.shuffle을 사용할 때 배열에 중복 데이터가 생성되는 예가 있습니까?
nurettin

예-답변에 포함되어 있습니다. "예제"섹션을 참조하십시오. ;)
Gordon Bean

신경 쓰지 마라, 나는 세 가지 요소를보고 그것이 같다고 생각했다. 좋은 발견
nurettin

1
random.shuffle문서는 소리한다 NumPy와 배열을 사용하지 마십시오
winterlight

10

단일 라이너의 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]


6

'print func (foo)'는 'foo'와 함께 호출 될 때 'func'의 반환 값을 인쇄합니다. 그러나 'shuffle'은 목록이 수정되므로 아무것도 인쇄하지 않으므로 반환 유형으로 None을 갖습니다. 해결 방법 :

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

# print it
print(b)

함수형 프로그래밍 스타일에 더 관심이 있다면 다음과 같은 래퍼 함수를 ​​만들 수 있습니다.

def myshuffle(ls):
    random.shuffle(ls)
    return ls

2
이 목록에 대한 참조를 전달하므로 원본이 수정됩니다. 다음을 사용하여 셔플하기 전에 목록을 복사 할 수 있습니다 deepcopy
shivram.ss

@ shivram.ss이 경우에는 random.sample(ls, len(ls))해당 경로를 실제로 내려 가고 싶은 경우 와 같은 것을 원할 것 입니다.
Arda Xi

4

하나라는 함수를 정의 할 수 있습니다 shuffled(같은 의미에서 sortsorted)

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

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

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하십시오.


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']

두 목록으로 돌아가려면이 긴 목록을 두 개로 나눕니다.


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

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

작은 소개 나 설명이 도움이 되겠습니까?
kacase

이 기능은 셔플 활동에 도움이됩니다. 숫자 목록을 세 번 섞고 무작위 셔플이 발생 해야하는 세 번에 임의의 인수가 필요하지 않은 경우 무작위 인수를 True로 설정하십시오. 동일한 셔플 순서를 유지하려면 변경하지 말고 코드를 실행하십시오.
Josh Anish

이 함수의 호출자가 런타임시 랜덤 또는 비 랜덤 셔플을 원하는지 여부를 결정하는 유스 케이스가 없으므로이 함수는 두 가지로 나눠야합니다.
toolforger

비 랜덤 셔플이 무엇을해야하는지에 대한 설명은 없습니다. (접선에서는 답이 아니므로 질문이므로 스택 오버플로의 목적에 부합하지 않습니다.)
toolforger

1

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

0

소스 파일 random.py의 이름을 지정하지 않았고 작업 디렉토리에 random.pyc.라는 파일이 없는지 확인하십시오. 파이썬 임의 모듈 대신 프로그램이 로컬 random.py 파일을 가져 오려고 시도 할 수 있습니다. .


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

이 기능은 랜덤 모듈을 사용하지 않으려는 경우 도움이됩니다.
Pogramist

이 솔루션은 장황 할뿐만 아니라 비효율적입니다 (런타임은 목록 크기의 제곱에 비례합니다).
toolforger

두 번째 루프 _list.extend(list2)는보다 간결하고 효율적인 로 대체 될 수 있습니다 .
toolforger

매개 변수를 수정하는 Python 함수는 결과를 반환해서는 안됩니다. 그것은 단지 관습이지만 유용한 것입니다. 사람들은 종종 자신이 호출하는 모든 함수의 구현을 볼 시간이 없기 때문에 함수의 이름 만보고 결과가있는 사람은 그 함수를 보는 것에 매우 놀랄 것입니다 매개 변수를 업데이트하십시오.
toolforger

0
import random
class a:
    foo = "bar"

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

-1

셔플 링 프로세스는 "교체 중" 이므로 각 항목의 발생이 변경 될 수 있습니다! 최소한 목록에있는 항목도 목록에있을 때

예 :

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

후,

random.shuffle(ml)

[0]의 수는 9 또는 8 일 수 있지만 정확히 10은 아닙니다.


-1

계획 : 무거운 물건 들기를 위해 라이브러리에 의존하지 않고 셔플을 작성하십시오. 예 : 요소 0으로 시작하는 목록부터 시작하십시오. 6과 같이 새로운 임의의 위치를 ​​찾고 6에 0의 값을, 0에 6의 값을 넣으십시오. 요소 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

파이썬에서 변수를 다음과 같이 바꿀 수 있습니다 :my_list[i], my_list[j] = my_list[j], my_list[i]
Karolis Ryselis

-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 (마지막 행의 foo는 임의의 순서를 가짐)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.