Come verificare se tutti i seguenti elementi sono in un elenco?


114

Ho scoperto che c'è una domanda correlata, su come trovare se almeno un elemento esiste in un elenco:
Come verificare se uno dei seguenti elementi è in un elenco?

Ma qual è il modo migliore e pitonico per scoprire se tutti gli elementi esistono in un elenco?

Cercando tra i documenti ho trovato questa soluzione:

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

Un'altra soluzione sarebbe questa:

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

Ma qui devi scrivere di più.

Esistono altre soluzioni?


5
Cosa c'è che non va set(smaller) <= set(larger)?
eumiro

1
Penso che le tue seconde soluzioni con "tutto" mi sembrino perfette e pitoniche.
Jiho Noh

Risposte:


157

Gli operatori come <=in Python generalmente non vengono sovrascritti per indicare qualcosa di significativamente diverso da "minore o uguale a". È insolito che la libreria standard lo faccia: per me sa di API legacy.

Utilizzare l'equivalente e il metodo più chiaramente dal nome, set.issubset. Nota che non è necessario convertire l'argomento in un set; lo farà per te se necessario.

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

2
non sapevo che potevi passare la lista direttamente come argomento a issubset ... bello!
tsimbalar

1
Anche se sono d'accordo con il sentimento, sono abbastanza d'accordo con l'idea <=e il issubsetsignificato della stessa cosa. Perché non ti piace?
Kirk Strauser

2
@Just: In primo luogo, perché non è ovvio cosa <=significhi per un set senza cercarlo nei documenti o avere una conoscenza preliminare di ciò che significa nella teoria degli insiemi, mentre tutti sanno cosa issubsetsignifica automaticamente.
Glenn Maynard

2
Conosci l'operatore matematico per il sottoinsieme (non proprio)? fondamentalmente sembra più o meno come un arrotondato <=;)
dom0

amo questa soluzione. c'è un modo per ottenere una posizione di indice o un valore di elenco invece di un valore bool (True: False)?
Vlad Gulin

62

Probabilmente lo userei setnel modo seguente:

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

O viceversa :

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

Lo trovo un po 'più leggibile, ma potrebbe essere eccessivo. Gli insiemi sono particolarmente utili per calcolare l'unione / intersezione / differenze tra le raccolte, ma potrebbe non essere l'opzione migliore in questa situazione ...


In realtà, MySet.issubset(MyOtherSet)e MySet <= MyOtherSetsono la stessa cosa.
Wok

1
@wok: oh non lo sapevo, ma penso che la sintassi <= sia un po 'confusa in quanto una sintassi simile può essere utilizzata con gli elenchi, ma con un significato molto diverso.
tsimbalar

3
non è così confuso se ricordi che l'inclusione definisce un ordine parziale su qualsiasi insieme di insiemi. In realtà è un po 'confuso che <=abbia il significato che ha per le sequenze: ci si potrebbe aspettare che significhi "è una sottosequenza" piuttosto che un ordinamento lessicografico.
aaronasterling

1
@aaronasterling: mmm, personalmente non penso troppo all '"ordine parziale" quando digito il codice :-), ma sono d'accordo sul fatto che anche l'uso <=con le sequenze sembri strano, in qualche modo ...
tsimbalar

3
Mi sono imbattuto in un po 'di Gotcha qui vorrei menzionare: Se si utilizza questo metodo, si sta convertendo le vostre liste di set, il che significa che non duplicati. set(['a','a']).issubset(['a'])ritorna True.
Orangestar

11

Mi piacciono questi due perché sembrano i più logici, quest'ultimo è più breve e probabilmente più veloce (mostrato qui usando la setsintassi letterale che è stata backportata in Python 2.7):

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

La soluzione "all" è la più rapida quando la misuri con timeit (). Questa dovrebbe essere la risposta accettata.
Attersson

3

E se i tuoi elenchi contengono duplicati come questo:

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

I set non contengono duplicati. Quindi, la riga seguente restituisce True.

set(v2).issubset(v1)

Per contare i duplicati, puoi utilizzare il codice:

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) 

Quindi, la riga seguente restituisce False.

is_subseq(v2, v1)

1

Questo era quello che stavo cercando online ma sfortunatamente non l'ho trovato online ma durante la sperimentazione sull'interprete Python.

>>> case  = "caseCamel"
>>> label = "Case Camel"
>>> list  = ["apple", "banana"]
>>>
>>> (case or label) in list
False
>>> list = ["apple", "caseCamel"]
>>> (case or label) in list
True
>>> (case and label) in list
False
>>> list = ["case", "caseCamel", "Case Camel"]
>>> (case and label) in list
True
>>>

e se hai un lungo elenco di variabili contenute in un file sublist variable

>>>
>>> list  = ["case", "caseCamel", "Case Camel"]
>>> label = "Case Camel"
>>> case  = "caseCamel"
>>>
>>> sublist = ["unique banana", "very unique banana"]
>>>
>>> # example for if any (at least one) item contained in superset (or statement)
...
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
False
>>>
>>> sublist[0] = label
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>> # example for whether a subset (all items) contained in superset (and statement)
...
>>> # a bit of demorgan's law
...
>>> next((False for item in sublist if item not in list), True)
False
>>>
>>> sublist[1] = case
>>>
>>> next((False for item in sublist if item not in list), True)
True
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>>

0

Un esempio di come eseguire questa operazione utilizzando un'espressione lambda potrebbe essere:

issublist = lambda x, y: 0 in [_ in x for _ in y]

1
Si prega di aggiungere commenti per spiegare / elaborare la risposta
Sharad

0

Non è il caso di OP, ma - per chiunque voglia affermare l'intersezione nei dict e sia finito qui a causa di una scarsa ricerca su Google (ad es. Me) - devi lavorare con dict.items:

>>> a = {'key': 'value'}
>>> b = {'key': 'value', 'extra_key': 'extra_value'}
>>> all(item in a.items() for item in b.items())
True
>>> all(item in b.items() for item in a.items())
False

Questo perché dict.itemsrestituisce tuple di coppie chiave / valore e, proprio come qualsiasi oggetto in Python, sono intercambiabili comparabili

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.