115 votes

Quelle est la façon la plus pythonique d'extraire un élément aléatoire d'une liste ?

Disons que j'ai une liste x de longueur inconnue dont je veux extraire un élément au hasard de sorte que la liste ne contienne plus cet élément par la suite. Quelle est la manière la plus pythonique de faire cela ?

Je peux le faire en utilisant une combinaison peu pratique de pop , random.randint y len et aimerait voir des solutions plus courtes ou plus agréables :

import random
x = [1,2,3,4,5,6]
x.pop(random.randint(0,len(x)-1))

Ce que j'essaie de faire, c'est d'extraire consécutivement des éléments aléatoires d'une liste. (par exemple, extraire au hasard un élément et le déplacer dans un dictionnaire, extraire au hasard un autre élément et le déplacer dans un autre dictionnaire, ...).

Notez que j'utilise Python 2.6 et que je n'ai pas trouvé de solution via la fonction de recherche.

5voto

Dolf Andringa Points 150

Je sais qu'il s'agit d'une vieille question, mais c'est juste par souci de documentation :

Si vous (la personne qui cherche la même question sur Google) faites ce que je pense que vous faites, c'est-à-dire sélectionner un nombre k d'éléments au hasard dans une liste (où k<=len(yourlist)), mais en vous assurant que chaque élément n'est jamais sélectionné plus d'une fois (=échantillonnage sans remplacement), vous pourriez utiliser échantillon.aléatoire comme le suggère @j-f-sebastian. Mais sans en savoir plus sur le cas d'utilisation, je ne sais pas si c'est ce dont vous avez besoin.

3voto

Simeon Visser Points 30697

Une façon de procéder est la suivante :

x.remove(random.choice(x))

2voto

Noah McIlraith Points 1241

Bien qu'elle ne soit pas tirée de la liste, j'ai rencontré cette question sur Google en essayant d'obtenir X éléments aléatoires d'une liste sans doublons. Voici ce que j'ai finalement utilisé :

items = [1, 2, 3, 4, 5]
items_needed = 2
from random import shuffle
shuffle(items)
for item in items[:items_needed]:
    print(item)

Cela peut être légèrement inefficace, car vous mélangez une liste entière tout en n'en utilisant qu'une petite partie, mais je ne suis pas un expert en optimisation, je peux donc me tromper.

1voto

Mark Gerolimatos Points 341

Cette réponse est fournie avec l'aimable autorisation de @niklas-b :

" Vous voudrez probablement utiliser quelque chose comme pypi.python.org/pypi/blist "

Pour citer le Page de l'IPPJ :

...un type de liste avec une meilleure asymptotique similaires sur les petites listes

Le blist est un remplacement direct de la liste Python qui fournit de meilleures performances lors de la modification de grandes listes. Le paquetage blist comprend également fournit également sortedlist, sortedset, weaksortedlist, weaksortedset, sorteddict, et les types btuple.

On peut s'attendre à une baisse des performances au niveau de l'accès aléatoire et de l'exécution aléatoire. car il s'agit d'une structure de données de type "copie sur écriture". Cela va à l'encontre de nombreuses hypothèses d'utilisation des listes Python, à utiliser avec précaution .

CEPENDANT, si votre principal cas d'utilisation est de faire quelque chose d'étrange et de peu naturel avec une liste (comme dans l'exemple forcé donné par @OP, ou mon problème de file d'attente FIFO avec pass-over de Python 2.6), alors cela conviendra parfaitement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X