Nesnelerin bir listesini karıştırma


770

Bir nesneler listem var ve onları karıştırmak istiyorum. Ben random.shuffleyöntemi kullanabileceğini düşündüm , ama liste nesneler olduğunda bu başarısız gibi görünüyor. Nesneleri karıştırmak için bir yöntem var mı veya bunun başka bir yolu var mı?

import random

class A:
    foo = "bar"

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

print(random.shuffle(b))

Bu başarısız olur.


6
Nasıl başarısız olduğunu gösteren bir örnek verebilir misiniz? random.shuffle listedeki nesnelerin türüne göre değişmemelidir.
bayer

3
>>> a1 = a () >>> a2 = a () >>> b = [a1, a2] >>> b [<__ ana __. 0xb7df9e6c'deki bir örnek>, <__ ana __. 0xb7df9e2c'deki bir örnek>]> >> print random.shuffle (b) Yok
utdiscant

135
Aşağıda belirtildiği gibi, random.shuffle yeni bir karışık liste döndürmez; listeyi karıştırır. Bu yüzden "print random.shuffle (b)" dememelisiniz ve bunun yerine bir satırda karıştırmalı ve bir sonraki satıra b yazmalısınız.
Eli Courtwright

Numpy dizilerini karıştırmaya çalışıyorsanız, aşağıdaki cevabımı görün.
Gordon Bean

1
orijinal diziyi değiştirmeyen ancak yeni bir karıştırılmış dizi döndüren bir seçenek var mı?
Charlie Parker

Yanıtlar:


1241

random.shuffleçalışmalı. İşte nesnelerin listelendiği bir örnek:

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

Karıştırmanın yerinde çalıştığını ve Yok değerini döndürdüğünü unutmayın.


1
@seokhoonlee İkisi de. Mümkün olduğunda, işletim sisteminden gerçek bir rastgelelik kaynağı tarafından tohumlanan bir pseduo-rastgele sayı üretecidir. Kriptografi dışındaki herkes için rastgele "yeterli" dir. Bu, randommodülün belgelerinde ayrıntılı olarak verilmiştir .
dimo414

2
yeni bir liste için klon kullan
Mohammad Mahdi KouchakYazdi

8
orijinal diziyi değiştirmeyen ancak yeni bir karıştırılmış dizi döndüren bir seçenek var mı?
Charlie Parker

5
@CharlieParker: Bildiğimden değil. random.sample(x, len(x))Bir kopyasını kullanabilir ya da kopyalayabilirsiniz shuffle. Bunun için list.sortbenzer bir sorunu var, şimdi var list.sorted, ancak benzer bir varyantı yok shuffle.
tom10

6
seokhonlee için kripto güvenli rasgelelik, from random import SystemRandombunun yerine kullanın; cryptorand = SystemRandom()3 numaralı satırı ekle ve değiştircryptorand.shuffle(x)
17'de

115

Bildiğiniz gibi yerinde karıştırma sorun oldu. Ayrıca sık sık sorun yaşıyorum ve çoğu zaman bir listeyi nasıl kopyalayacağımı da unutuyor gibi görünüyor. Kullanma sample(a, len(a))kullanılarak çözüm len(a)numune büyüklüğü. Python belgeleri için https://docs.python.org/3.6/library/random.html#random.sample sayfasına bakın .

İşte random.sample()karıştırılmış sonucu yeni bir liste olarak döndüren basit bir sürüm .

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

orijinal diziyi değiştirmeyen ancak yeni bir karıştırılmış dizi döndüren bir seçenek var mı?
Charlie Parker

sadece listeyi kopyala @CharlieParker: old = [1,2,3,4,5]; new = list(old); random.shuffle(new); print(old); print(new)(değiştir; yeni satırlarla)
fjsj

old[:]ayrıca liste için sığ bir kopya yapabilir old.
Xiao

sample()bir veri analizinin prototiplenmesi için özellikle yararlıdır. sample(data, 2)bir boru hattının tutkal kodunu ayarlamak, sonra bunu adım adım genişletmek için len(data).
Katrin Leinweber

58

Bunu da almam biraz zaman aldı. Ancak shuffle için belgeler çok açık:

Liste x karıştırmak yerine ; dönüş Yok.

Yani yapmamalısın print(random.shuffle(b)). Bunun yerine yap random.shuffle(b)ve sonra 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

Zaten numpy kullanıyorsanız (bilimsel ve finansal uygulamalar için çok popüler) kendinize bir ithalat kaydedebilirsiniz.

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

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


Bu cevap hakkında sevdiğim şey, rastgele tohumu nümerik olarak kontrol edebilmem. Bahse girerim rastgele modülde bunu yapmanın bir yolu var ama şu an benim için açık değil ... yani daha fazla okumaya ihtiyacım var.
VanBantam

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

Benim için iyi çalışıyor. Rastgele yöntemi ayarladığınızdan emin olun.


Hala benim için çalışmıyor, düzenlenen sorudaki örnek koduma bakın.
utdiscant

4
İkinci parametre varsayılan olarak random.random olur. Dışarıda bırakmak tamamen güvenlidir.
cbare

3
@alvas random.shuffle (a) herhangi bir şey döndürmez, yani Yok döndürür. Yani bir dönüş değeri kontrol etmek zorunda değilsiniz.
sonus21

15

Birden fazla listeniz varsa, önce permütasyonu (listeyi karıştırma / listedeki öğeleri yeniden düzenleme yönteminiz) tanımlayıp tüm listelere uygulamak isteyebilirsiniz:

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

Listeleriniz numpy dizilerse daha basittir:

import numpy as np

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

mpu

Ben işlevi mpuolan küçük yarar paketi oluşturduk 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_shuffleRastgele sayıda argüman alan unutmayın . Böylece üç veya daha fazla listeyi de karıştırabilirsiniz.


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

Bu alternatif, sipariş işlevini değiştirmek istediğiniz bazı uygulamalar için yararlı olabilir.


Ayrıca, bunun sayesinde sortedfonksiyonel bir karışıklık olduğunu unutmayın (eğer bu tür bir şey içindeyseniz).
Inaimathi

1
Bu, Timsort'un kararlılığı nedeniyle değerleri gerçekten rastgele dağıtmaz. (Aynı tuşa sahip değerler orijinal sıralarında bırakılır.) EDIT: Sanırım 64-bit float çarpışma riski oldukça az olduğu için önemli değil.
Mateen Ulhaq

10

Bazı durumlarda numpy dizileri kullanılırken, dizide random.shuffleoluşturulan yinelenen veriler kullanılır .

Bir alternatif kullanmaktır numpy.random.shuffle. Zaten numpy ile çalışıyorsanız, bu genel üzerinde tercih edilen yöntemdir random.shuffle.

numpy.random.shuffle

Misal

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

Kullanma 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]])

Kullanma 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
Ayrıca numpy.random.permutationilginizi çekebilir: stackoverflow.com/questions/15474159/shuffle-vs-permute-numpy
Gordon Bean

Random.shuffle kullanılırken bir dizide yinelenen veri oluşturulmasına örnek var mı?
nurettin

Evet - cevabıma dahil edildi. "Örnek" başlıklı bölüme bakın. ;)
Gordon Bean

Boşver, üç element gördüm ve aynı olduğunu düşündüm. Güzel bulmak
nurettin

1
random.shufflebelgelerin bağırması gerekir
Numpy

10

Tek gömlekler random.sample(list_to_be_shuffled, length_of_the_list)için bir örnekle kullanın :

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

çıkışlar: [2, 9, 7, 8, 3, 0, 4, 1, 6, 5]


6

'print func (foo)', 'foo' ile çağrıldığında 'func' dönüş değerini yazdıracaktır. Ancak 'shuffle', dönüş tipi olarak None'a sahiptir, çünkü liste yerinde değiştirileceğinden hiçbir şey yazdırmaz. Çözüm:

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

# print it
print(b)

İşlevsel programlama stiline daha fazla iseniz, aşağıdaki sarmalayıcı işlevini yapmak isteyebilirsiniz:

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

2
Bu listeye bir referans ilettiği için orijinal değiştirilir. Kullanarak karıştırma önce listeyi kopyalamak isteyebilirsiniz deepcopy
shivram.ss

@ shivram.ss Bu durumda, random.sample(ls, len(ls))gerçekten o rotadan gitmek istiyor gibi bir şey istersiniz .
Arda Xi

4

Kişi denilen bir işlevi tanımlayabilir shuffled(aynı anlamda sortvs sorted)

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 yerinde, bu nedenle sonucu yazdırmayın, yani Noneliste.


1

Bunun için gidebilirsiniz:

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

iki listeye geri dönmek isterseniz, bu uzun listeyi ikiye böldünüz.


1

listeyi parametre olarak alan ve listenin karışık sürümünü döndüren bir işlev oluşturabilirsiniz:

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

küçük bir giriş ya da açıklama yardımcı olur mu?
kacase

işlev karıştırma etkinliği için yararlıdır, bir liste listesini üç kez karıştırmanız gerektiğini ve üç kez rasgele karıştırmanın gerekli olduğunu hayal edin, sonra rastgele çalışmaya gerek duymuyorsanız ve rastgele istiyorsanız aynı karıştırma sırası korunacak sonra hiçbir değişiklik yapmayın, sadece kodu çalıştırın.
Josh Anish

Bu işlevin arayanının çalışma zamanında rasgele veya rasgele olmayan karıştırmayı isteyip istemediğine karar vereceği bir kullanım durumu olmadığından, bu işlev ikiye bölünmelidir.
toolforger

Rastgele olmayan shuffle'ın ne yapması gerektiği konusunda bir açıklama yoktur. (Bir teğet üzerinde, bu bir cevap değildir, bu yüzden soru, bu nedenle Yığın Taşması amacına hizmet etmez.)
toolforger

1

shuffle veya sample kullanabilirsiniz. ikisi de rastgele bir modülden geliyor.

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

VEYA

import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1

0

Kaynak dosyanızı random.py olarak adlandırmadığınızdan ve çalışma dizininizde random.pyc adlı bir dosya bulunmadığından emin olun. .


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

Rastgele modül kullanmak istemiyorsanız bu işlev size yardımcı olabilir
Pogramist

Bu çözüm sadece ayrıntılı değil, verimsizdir (çalışma zamanı, liste boyutunun karesiyle orantılıdır).
toolforger

İkinci döngü _list.extend(list2), daha özlü VE daha verimli olan ile değiştirilebilir .
toolforger

Bir parametreyi değiştiren bir Python işlevi hiçbir zaman sonuç döndürmemelidir. Bu sadece bir kongre, ama yararlı bir konudur: İnsanlar genellikle çağırdıkları tüm işlevlerin uygulanmasına bakmak için zamandan yoksundur, bu nedenle sadece işlevinizin adını gören ve bir sonucu olan herkes işlevi görmek için çok şaşırır. parametresini güncelleyin.
toolforger

0
import random
class a:
    foo = "bar"

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

-1

Karıştırma işlemi "değiştirilerek" yapılır , bu nedenle her öğenin oluşumu değişebilir! En azından listenizdeki öğeler de listelendiğinde.

Örneğin,

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

Sonra,

random.shuffle(ml)

[0] sayısı 9 veya 8 olabilir, ancak tam olarak 10 olamaz.


-1

Plan: Ağır kaldırmayı yapmak için bir kütüphaneye güvenmeden karıştırmayı yazın. Örnek: 0 öğesinden başlayarak listeden baştan başlayın; bunun için yeni bir rastgele konum bulun, örneğin 6, 0'ın değerini 6 ve 6'nın 0 değerine yerleştirin. Eleman 1'e geçin ve bu işlemi tekrarlayın, vb.

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

-2

İyi çalışıyor. Burada liste nesneleri olarak fonksiyonları ile deniyorum:

    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()

Yazdırır: foo1 foo2 foo3 foo2 foo3 foo1 (son satırdaki foos rastgele bir sıraya sahiptir)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.