Potasuj tablicę za pomocą pytona, losowo uporządkuj elementy tablicy za pomocą pytona

261

Jaki jest najłatwiejszy sposób przetasowania tablicy za pomocą Pythona?

davethegr8
źródło
28
+1 za migrację najbardziej przydatnych bitów dokumentacji Pythona do zawsze najlepszego formatu SO Q&A.
charleslparker
1
czy istnieje opcja, która nie powoduje mutacji oryginalnej tablicy, ale zwraca nową losową tablicę?
Charlie Parker
5
możesz uzyskać nową tablicę (niemodyfikowaną) za pomocą new_array = random.sample( array, len(array) ).
Charlie Parker

Odpowiedzi:

464
import random
random.shuffle(array)
David Z
źródło
3
czy istnieje opcja, która nie powoduje mutacji oryginalnej tablicy, ale zwraca nową losową tablicę?
Charlie Parker
@Charlie Dobrze byłoby zadać osobne pytanie. (Może ktoś już o to pytał.)
David Z
13
Jak na ironię, ta strona jest największym hitem w Google, kiedy właśnie szukałem „tablicy shuffle python”
Joshua Huber,
2
@Charlie ludzie Google te pytania, aby mogli znaleźć odpowiedzi na nie w miejscach takich jak przepełnienie stosu. Dopóki nie jest to duplikat, nie ma nic złego w uczynieniu z przepełnienia stosu opcji jako zasobu
Matt
@javadba To właściwie miała być odpowiedź na pierwsze pytanie. Nie ma nic złego w zadawaniu pytań na temat przepełnienia stosu, nawet jeśli można go znaleźć przy kopaniu w google. Pozwala to przyszłym ludziom znaleźć odpowiedź na temat przepełnienia stosu podczas własnego kopania.
Matt
108
import random
random.shuffle(array)
Douglas Leeder
źródło
2
czy istnieje opcja, która nie powoduje mutacji oryginalnej tablicy, ale zwraca nową losową tablicę?
Charlie Parker
36

Alternatywny sposób to zrobić za pomocą sklearn

from sklearn.utils import shuffle
X=[1,2,3]
y = ['one', 'two', 'three']
X, y = shuffle(X, y, random_state=0)
print(X)
print(y)

Wynik:

[2, 1, 3]
['two', 'one', 'three']

Korzyść: możesz losować wiele tablic jednocześnie, bez zakłócania mapowania. A „random_state” może kontrolować tasowanie w celu uzyskania powtarzalnego zachowania.

Qy Zuo
źródło
1
Dzięki, bardzo przydatne jest przetasowanie dwóch tablic jednocześnie.
Dmitry,
1
Szukałem tego, TNX!
nO
2
jest to bardziej kompletne (i często bardziej przydatne) niż zaakceptowana odpowiedź
javadba
21

Inne odpowiedzi są najłatwiejsze, jednak nieco denerwujące jest to, że random.shufflemetoda nic nie zwraca - po prostu sortuje podaną listę. Jeśli chcesz połączyć wywołania lub po prostu móc zadeklarować przetasowaną tablicę w jednym wierszu, możesz:

    import random
    def my_shuffle(array):
        random.shuffle(array)
        return array

Następnie możesz wykonać linie takie jak:

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):
Mark Rhodes
źródło
7
Nie zwraca niczego specjalnie, ponieważ próbuje przypomnieć ci, że działa, zmieniając wprowadzone dane. (Może to zaoszczędzić pamięć.) Twoja funkcja zmienia również wprowadzane dane.
John Y,
2
Myślę, że to kwestia stylu. Osobiście wolę fakt, że mogę napisać jedną linię, aby osiągnąć to, co zajęłoby parę inaczej. Wydaje mi się dziwne, że język, który dąży do tego, aby programy były jak najkrótsze, nie zwraca w takich przypadkach zwracanego obiektu. Ponieważ zmienia on wprowadzone dane, możesz bez problemu wywołać wywołanie random.shuffle dla wywołania tej wersji.
Mark Rhodes,
12
Python tak naprawdę nie chce być tak krótki, jak to możliwe. Python dąży do zrównoważenia czytelności z ekspresją. Tak się składa, że ​​jest dość krótki, głównie dlatego, że jest to język bardzo wysokiego poziomu. Wbudowane przez Pythona zazwyczaj (nie zawsze) starają się albo być „funkcjonalne” (zwracają wartość, ale nie mają efektów ubocznych), albo „proceduralne” (działają poprzez efekty uboczne i nic nie zwracają). Idzie to w parze z dość ścisłym rozróżnieniem Pythona między instrukcjami i wyrażeniami.
John Y,
Miły. Sugeruję zmienić nazwę na my_shuffle, aby natychmiast zobaczyć różnicę w kodzie.
Jabba
Może, ale może to być przedwczesna optymalizacja (może być pomocna, ale potrzeba przetasowania nie wymaga jawnego zwracania tablicy). Również losowanie (tablica), a następnie użycie losowania będzie składać się tylko z 2 wierszy, w przeciwieństwie do 3 + n (użycie razy), ale myślę, że byłoby to oszczędzanie, jeśli użyjesz go wiele razy. Oto świetny film, który omawia tego rodzaju rzeczy (np. Wymagania fantomowe i przedwczesna optymalizacja) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton
12

W przypadku zwykłych list w języku Python random.shuffle()wykona zadanie dokładnie tak, jak pokazują poprzednie odpowiedzi.

Ale jeśli chodzi o ndarray( numpy.array), random.shufflewydaje się , że łamie oryginał ndarray. Oto przykład:

import random
import numpy as np
import numpy.random

a = np.array([1,2,3,4,5,6])
a.shape = (3,2)
print a
random.shuffle(a) # a will definitely be destroyed
print a

Po prostu użyj: np.random.shuffle(a)

Jak random.shuffle, np.random.shuffletasuje tablicę w miejscu.

Shuai Zhang
źródło
2
co dokładnie oznacza zniszczone? (Mam na myśli, w tym kontekście - nie jestem ELL.)
dbliss
Cóż, jeśli spróbuję A = np. Tablica (zakres (9)). Przekształć ([3,3])
Nicholas McCarthy
11

Na wypadek, gdybyś potrzebował nowej tablicy, której możesz użyć sample:

import random
new_array = random.sample( array, len(array) )
Charlie Parker
źródło
3

Możesz posortować tablicę za pomocą losowego klucza

sorted(array, key = lambda x: random.random())

klucz można odczytać tylko raz, więc porównywanie pozycji podczas sortowania jest nadal skuteczne.

ale wygląda na to, random.shuffle(array)że będzie szybszy, ponieważ napisano w C.

Trinh Hoang Nhu
źródło
1
czy tworzy to nowy losowy element dla każdego elementu tablicy?
javadba
@javadba Nie, po prostu posortuj tablicę według losowego indeksu, który ostatecznie przetasuje tablicę
Trinh Hoang Nhu
1
Niestety ja może nie usunąć nie znaczy, że arraymam na myśli Randomelementu: czyli w może być tworzenie nowych instancji klasy każdym razem. Nie jestem do końca pewien: w ten sposób byłby to niewłaściwy sposób: należy utworzyć a, a następnie wywołać . Ale nie jestem pewien, jak działa Pythonlambdarandom.random()RandomjavaRandom rng = Random()rng.nextGaussian()random.random()
javadba
1
Podczas gdy Twój kod może być poprawny jako odpowiedź, ale Opracowanie tego, co robi Twój kod, może poprawić jakość twojej odpowiedzi. Zapoznaj się z artykułem: Jak napisać dobrą odpowiedź?
LuFFy,
1

Oprócz poprzednich odpowiedzi chciałbym wprowadzić inną funkcję.

numpy.random.shufflea także random.shufflewykonywać tasowanie w miejscu. Jeśli jednak chcesz zwrócić tasowaną tablicę, skorzystaj z numpy.random.permutationtej funkcji.

Szabla
źródło
1

Nie wiem, czy użyłem, random.shuffle()ale zwraca mi „Brak”, więc napisałem to, może komuś pomóc

def shuffle(arr):
    for n in range(len(arr) - 1):
        rnd = random.randint(0, (len(arr) - 1))
        val1 = arr[rnd]
        val2 = arr[rnd - 1]

        arr[rnd - 1] = val1
        arr[rnd] = val2

    return arr
Jeeva
źródło
2
tak, zwraca Brak, ale tablica jest zmodyfikowana, jeśli naprawdę chcesz coś zwrócić, zrób to importuj losowo def shuffle (arr): random.shuffle (arr) return arr
user781903
0
# arr = numpy array to shuffle

def shuffle(arr):
    a = numpy.arange(len(arr))
    b = numpy.empty(1)
    for i in range(len(arr)):
        sel = numpy.random.random_integers(0, high=len(a)-1, size=1)
        b = numpy.append(b, a[sel])
        a = numpy.delete(a, sel)
    b = b[1:].astype(int)
    return arr[b]
sudeep
źródło
0

Należy pamiętać, że random.shuffle()nie należy go stosować w tablicach wielowymiarowych, ponieważ powoduje to powtórzenia.

Wyobraź sobie, że chcesz przetasować tablicę wzdłuż jej pierwszego wymiaru, możemy utworzyć następujący przykład testu:

import numpy as np
x = np.zeros((10, 2, 3))

for i in range(10):
   x[i, ...] = i*np.ones((2,3))

tak, że wzdłuż pierwszej osi i-ty element odpowiada macierzy 2x3, w której wszystkie elementy są równe i.

Jeśli użyjemy prawidłowej funkcji losowania dla tablic wielowymiarowych, tzn np.random.shuffle(x). Tablica zostanie przetasowana wzdłuż pierwszej osi zgodnie z potrzebami. Jednak użycie random.shuffle(x)spowoduje powtórzenia. Możesz to sprawdzić, uruchamiając len(np.unique(x))po tasowaniu, co daje 10 (zgodnie z oczekiwaniami) z, np.random.shuffle()ale tylko około 5 podczas używania random.shuffle().

Mądra chmura
źródło