136 votes

Python : Sélectionner un sous-ensemble dans une liste en fonction d'un ensemble d'index

J'ai plusieurs listes ayant toutes le même nombre d'entrées (chacune spécifiant une propriété d'objet) :

property_a = [545., 656., 5.4, 33.]
property_b = [ 1.2,  1.3, 2.3, 0.3]
...

et une liste avec des drapeaux de même longueur

good_objects = [True, False, False, True]

(qui pourrait facilement être remplacée par une liste d'index équivalente) :

good_indices = [0, 3]

Quel est le moyen le plus simple de générer de nouvelles listes ? property_asel , property_bsel ... qui ne contiennent que les valeurs indiquées soit par l'élément True ou les indices ?

property_asel = [545., 33.]
property_bsel = [ 1.2, 0.3]

183voto

KennyTM Points 232647

Vous pouvez simplement utiliser compréhension de la liste :

property_asel = [val for is_good, val in zip(good_objects, property_a) if is_good]

ou

property_asel = [property_a[i] for i in good_indices]

Cette dernière est plus rapide car il y a moins de good_indices que la longueur de property_a en supposant que good_indices sont précalculés au lieu d'être générés à la volée.


Éditer : La première option est équivalente à itertools.compress disponible depuis Python 2.7/3.1. Voir aussi @Gary Kerr La réponse de l'auteur de l'article est la suivante.

property_asel = list(itertools.compress(property_a, good_objects))

35voto

Wolph Points 28062

Je vois deux options.

  1. Utilisation de numpy :

    property_a = numpy.array([545., 656., 5.4, 33.])
    property_b = numpy.array([ 1.2,  1.3, 2.3, 0.3])
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = property_a[good_objects]
    property_bsel = property_b[good_indices]
  2. Utiliser une liste de compréhension et la zipper :

    property_a = [545., 656., 5.4, 33.]
    property_b = [ 1.2,  1.3, 2.3, 0.3]
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = [x for x, y in zip(property_a, good_objects) if y]
    property_bsel = [property_b[i] for i in good_indices]

18voto

PreludeAndFugue Points 3504

Utiliser la fonction intégrée fermeture éclair

property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]

EDIT

Je viens d'examiner les nouvelles fonctionnalités de la version 2.7. Il y a maintenant une fonction dans le module itertools qui est similaire au code ci-dessus.

http://docs.python.org/library/itertools.html#itertools.compress

itertools.compress('ABCDEF', [1,0,1,0,1,1]) =>
  A, C, E, F

11voto

Eyrofire Points 85

En supposant que vous ne disposiez que de la liste des éléments et d'une liste d'indices vrais/obligatoires, cette méthode devrait être la plus rapide :

property_asel = [ property_a[index] for index in good_indices ]

Cela signifie que la sélection des propriétés ne fera qu'autant de tours qu'il y a d'indices vrais/nécessaires. Si vous avez beaucoup de listes de propriétés qui suivent les règles d'une seule liste de balises (vrai/faux), vous pouvez créer une liste d'indices en utilisant les mêmes principes de compréhension de liste :

good_indices = [ index for index, item in enumerate(good_objects) if item ]

Cette méthode parcourt chaque élément de good_objects (tout en se souvenant de son index avec enumerate) et ne renvoie que les index où l'élément est vrai.


Pour ceux qui ne comprennent pas la liste, voici une version anglaise en prose avec le code en gras :

lister les index pour tout groupe de index, article qui existe en un énumération de bons objets , si (où) le item is True

-3voto

FredAndre Points 11

Les langages Matlab et Scilab offrent une syntaxe plus simple et plus élégante que Python pour la question que vous posez, donc je pense que le mieux que vous puissiez faire est d'imiter Matlab/Scilab en utilisant le package Numpy en Python. Ce faisant, la solution à votre problème est très concise et élégante :

from numpy import *
property_a = array([545., 656., 5.4, 33.])
property_b = array([ 1.2,  1.3, 2.3, 0.3])
good_objects = [True, False, False, True]
good_indices = [0, 3]
property_asel = property_a[good_objects]
property_bsel = property_b[good_indices]

Numpy tente d'imiter Matlab/Scilab mais cela a un coût : vous devez déclarer chaque liste avec le mot-clé "array", ce qui surchargera votre script (ce problème n'existe pas avec Matlab/Scilab). Notez que cette solution est limitée aux tableaux de nombres, ce qui est le cas dans votre exemple.

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