2010-10-14 3 views
53

Je trouve qu'il y est lié question, sur la façon de trouver si existe au moins un élément dans une liste:
How to check if one of the following items is in a list?Comment vérifier si tous les éléments suivants sont dans une liste?

Mais quelle est la meilleure et pythonique pour savoir si tous les éléments existent dans une liste?

une recherche dans les documents que je trouve cette solution:

>>> l = ['a', 'b', 'c'] 
>>> set(['a', 'b']) <= set(l) 
True 
>>> set(['a', 'x']) <= set(l) 
False 

Autre solution serait:

>>> l = ['a', 'b', 'c'] 
>>> all(x in l for x in ['a', 'b']) 
True 
>>> all(x in l for x in ['a', 'x']) 
False 

Mais ici vous devez faire plus taper.

Existe-t-il d'autres solutions?

+4

Qu'est-ce qui ne va pas avec 'set (smaller) <= set (larger)'? – eumiro

Répondre

42

Les opérateurs comme <= en Python ne sont généralement pas considérés comme signifiant quelque chose de significativement différent de "moins de ou égal à ". C'est inhabituel pour la bibliothèque standard de le faire - ça sent l'ancienne API pour moi.

Utilisez la méthode équivalente et plus clairement nommée, set.issubset. Notez que vous n'avez pas besoin de convertir l'argument en ensemble; ça va le faire pour vous si nécessaire.

set(['a', 'b']).issubset(['a', 'b', 'c']) 
+2

ne savait pas que vous pourriez passer la liste directement comme un argument à issubset ... sympa! – tsimbalar

+0

Même si je suis d'accord avec le sentiment, je suis assez OK avec l'idée de '<' 'et' issubset' signifie la même chose. Pourquoi ne l'aimez-vous pas? –

+2

@Just: Principalement parce que ce n'est pas évident ce que '<= signifie pour un ensemble sans le chercher dans les docs ou avoir une connaissance préalable de ce que cela signifie en théorie des ensembles, alors que tout le monde sait ce que issubset signifie automatiquement. –

49

J'utiliserions probablement set de la manière suivante:

set(l).issuperset(set(['a','b'])) 

ou l'inverse:

set(['a','b']).issubset(set(l)) 

Je trouve un peu plus facile à lire, mais il peut être trop tuer. Les ensembles sont particulièrement utiles pour calculer union/intersection/différences entre les collections, mais ce n'est peut-être pas la meilleure option dans cette situation ...

+0

En fait, 'MySet.issubset (MyOtherSet)' et 'MySet <= MyOtherSet' sont les mêmes. – Wok

+1

@wok: oh je ne le savais pas, mais je pense que la syntaxe <= est un peu déroutante car une syntaxe similaire peut être utilisée avec des listes, mais avec une signification très différente. – tsimbalar

+2

ce n'est pas vraiment déroutant si vous vous rappelez que l'inclusion définit un ordre partiel sur n'importe quel ensemble d'ensembles.Il est en fait un peu déroutant que '<=' ait le sens qu'il a pour les séquences: on pourrait s'attendre à ce qu'il signifie 'est une sous-séquence' de plutôt que l'ordre lexicographique. – aaronasterling

4

J'aime ces deux parce qu'ils semblent le plus logique, cette dernière étant plus courte et probablement le plus rapide (ici en utilisant de nouveaux Set littéraux qui étaient backported à Python 2.7):

all(x in {'a', 'b', 'c'} for x in ['a', 'b']) 
# or 
{'a', 'b'}.issubset({'a', 'b', 'c'}) 
1

Que faire si votre les listes contiennent des doublons comme ceci:

v1 = ['s', 'h', 'e', 'e', 'p'] 
v2 = ['s', 's', 'h'] 

Les ensembles ne contiennent pas de doublons. Ainsi, la ligne suivante renvoie True.

set(v2).issubset(v1) 

Pour compter les doublons, vous pouvez utiliser le code:

v1 = sorted(v1) 
v2 = sorted(v2) 


def is_subseq(v2, v1): 
    """Check whether v2 is a subsequence of v1.""" 
    it = iter(v1) 
    return all(c in it for c in v2) 

Ainsi, la ligne suivante retourne Faux.

is_subseq(v2, v1) 
Questions connexes