Mélanger un tableau avec python, randomiser l'ordre des éléments du tableau avec python

261

Quelle est la façon la plus simple de mélanger un tableau avec python?

davethegr8
la source
28
+1 pour migrer les bits les plus utiles de la documentation python vers le format SO Q&A toujours supérieur.
charleslparker
1
existe-t-il une option qui ne mute pas le tableau d'origine mais renvoie un nouveau tableau mélangé?
Charlie Parker
5
vous pouvez obtenir un nouveau tableau (non modifié) avec new_array = random.sample( array, len(array) ).
Charlie Parker

Réponses:

464
import random
random.shuffle(array)
David Z
la source
3
existe-t-il une option qui ne mute pas le tableau d'origine mais renvoie un nouveau tableau mélangé?
Charlie Parker
@Charlie Ce serait une bonne chose à poser dans une question distincte. (Peut-être que quelqu'un d'autre l'a déjà demandé.)
David Z
13
Ironiquement, cette page est la plus populaire de Google lorsque je viens de rechercher «tableau de mélange de python»
Joshua Huber
2
@Charlie personnes Google ces questions afin qu'ils puissent y trouver des réponses sur des endroits comme le débordement de pile. Tant qu'il ne s'agit pas d'un doublon, il n'y a rien de mal à faire du débordement de pile une option en tant que ressource
Matt
@javadba Cela devait en fait être une réponse à la première question. Il n'y a rien de mal à poser des questions sur le débordement de la pile, même s'il peut être trouvé en creusant sur Google. Il permet aux futurs utilisateurs de trouver la réponse sur stackoverflow lorsqu'ils effectuent leur propre fouille.
Matt
108
import random
random.shuffle(array)
Douglas Leeder
la source
2
existe-t-il une option qui ne mute pas le tableau d'origine mais renvoie un nouveau tableau mélangé?
Charlie Parker
36

Autre moyen de le faire en utilisant 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)

Production:

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

Avantage: vous pouvez randomiser plusieurs tableaux simultanément sans perturber le mappage. Et 'random_state' peut contrôler le brassage pour un comportement reproductible.

Qy Zuo
la source
1
Merci, il est très utile de mélanger deux tableaux à la fois.
Dmitry
1
Je cherchais ça, TNX!
2018
2
c'est plus complet (et souvent plus utile) que la réponse acceptée
javadba
21

Les autres réponses sont les plus simples, mais il est un peu ennuyeux que la random.shuffleméthode ne retourne rien - elle trie simplement la liste donnée. Si vous souhaitez chaîner des appels ou simplement être en mesure de déclarer un tableau mélangé sur une seule ligne, vous pouvez le faire:

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

Ensuite, vous pouvez faire des lignes comme:

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):
Mark Rhodes
la source
7
Il ne renvoie rien de particulier car il essaie de vous rappeler qu'il fonctionne en modifiant l'entrée en place. (Cela peut économiser de la mémoire.) Votre fonction modifie également son entrée en place.
John Y
2
Je suppose que c'est une question de style. Personnellement, je préfère le fait que je puisse écrire une seule ligne pour réaliser ce qui prendrait un couple autrement. Il me semble étrange qu'un langage qui vise à permettre aux programmes d'être aussi courts que possible n'a pas tendance à retourner l'objet passé dans ces cas. Puisqu'il modifie l'entrée en place, vous pouvez remplacer un appel à random.shuffle pour un appel à cette version sans problème.
Mark Rhodes
12
Python n'a pas pour objectif d'être aussi bref que possible. Python vise à équilibrer la lisibilité et l'expressivité. Il se trouve que cela est assez bref, principalement parce que c'est un langage de très haut niveau. Les propres fonctionnalités intégrées de Python s'efforcent généralement (pas toujours) d' être soit "fonctionnelles" (renvoyer une valeur, mais n'ont pas d'effets secondaires) ou être "procédurales" (fonctionner via des effets secondaires, et ne rien retourner). Cela va de pair avec la distinction assez stricte de Python entre les instructions et les expressions.
John Y
Agréable. Je suggère de le renommer en my_shuffle pour voir immédiatement la différence dans le code.
Jabba
Peut-être, mais cela pourrait être une optimisation prématurée (cela pourrait être utile, mais la nécessité de mélanger n'exige pas explicitement la nécessité de retourner le tableau). De plus, shuffle (tableau) suivi d'une certaine utilisation de shuffle ne serait que de 2 lignes au lieu de 3 + n (fois l'utilisation), bien que je suppose que ce serait une économie si vous l'utilisez plusieurs fois. Voici une excellente vidéo qui discute de ce type de chose (par exemple, les exigences fantômes et l'optimisation prématurée) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton
12

Lorsque vous traitez avec des listes Python régulières, random.shuffle()fera le travail comme le montrent les réponses précédentes.

Mais quand il s'agit de ndarray( numpy.array), random.shufflesemble casser l'original ndarray. Voici un exemple:

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

Utilisez simplement: np.random.shuffle(a)

Comme random.shuffle, np.random.shufflemélange le tableau en place.

Shuai Zhang
la source
2
qu'est-ce que détruit signifie exactement? (je veux dire, dans ce contexte - je ne suis pas un ELL.)
dbliss
Eh bien, si j'essaie A = np.array (range (9)). Reshape ([3,3])
Nicholas McCarthy
11

Au cas où vous voudriez un nouveau tableau, vous pouvez utiliser sample:

import random
new_array = random.sample( array, len(array) )
Charlie Parker
la source
3

Vous pouvez trier votre tableau avec une clé aléatoire

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

la clé ne doit être lue qu'une seule fois, donc la comparaison de l'élément pendant le tri est toujours efficace.

mais ressembler random.shuffle(array)sera plus rapide car il est écrit en C

Trinh Hoang Nhu
la source
1
cela crée-t-il un nouvel élément aléatoire pour chaque élément du tableau?
javadba
@javadba Non, il suffit de trier un tableau par index aléatoire qui finira par mélanger le tableau
Trinh Hoang Nhu
1
Désolé, je n'étais peut-être pas clair, je ne voulais pas dire que arrayje voulais dire l' Randomélément: c'est-à-dire que dans lambdale random.random()pourrait générer une nouvelle Randominstance de classe à chaque fois. Je ne suis pas vraiment sûr: javace serait la mauvaise façon de le faire: vous devez créer un Random rng = Random(), puis invoquer le rng.nextGaussian(). Mais random.random()
je
1
Bien que votre code puisse être corrigé comme réponse Mais en élaborant ce que fait votre code, cela peut améliorer la qualité de votre réponse. Consultez l'article: comment écrire une bonne réponse?
LuFFy
1

En plus des réponses précédentes, je voudrais introduire une autre fonction.

numpy.random.shuffleainsi que d' random.shuffleeffectuer un brassage sur place. Cependant, si vous souhaitez renvoyer un tableau mélangé, numpy.random.permutationc'est la fonction à utiliser.

Sabre
la source
1

Je ne sais pas si je l'ai utilisé, random.shuffle()mais cela me renvoie `` Aucun '', alors j'ai écrit ceci, cela pourrait être utile à quelqu'un

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
la source
2
oui, il renvoie None, mais le tableau est modifié, si vous voulez vraiment renvoyer quelque chose, effectuez cette importation aléatoire aléatoire 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
la source
0

Sachez que cela random.shuffle()ne doit pas être utilisé sur des tableaux multidimensionnels car cela provoque des répétitions.

Imaginez que vous vouliez mélanger un tableau le long de sa première dimension, nous pouvons créer l'exemple de test suivant,

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

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

de sorte que le long du premier axe, le i-ème élément correspond à une matrice 2x3 où tous les éléments sont égaux à i.

Si nous utilisons la fonction de lecture aléatoire correcte pour les tableaux multidimensionnels, c'est np.random.shuffle(x)-à- dire que le tableau sera mélangé le long du premier axe comme souhaité. Cependant, l'utilisation random.shuffle(x)entraînera des répétitions. Vous pouvez vérifier cela en exécutant len(np.unique(x))après la lecture aléatoire, ce qui vous donne 10 (comme prévu) avec np.random.shuffle()mais seulement environ 5 lors de l'utilisation random.shuffle().

Nuage sage
la source