2012-08-15 19 views

risposta

3

Utilizzando list comprehension, data:

mylist = [['a','b','c'],['d','e','f']] 
'd' in [j for i in mylist for j in i] 

rendimenti:

True 

e questo potrebbe anche essere fatto con un generatore (come mostrato da @AshwiniC haudhary)

aggiornamento basato sul commento qui sotto:

Qui è la stessa di lista, ma utilizzando i nomi delle variabili più descrittivi:

'd' in [elem for sublist in mylist for elem in sublist] 

I costrutti di loop nella parte di lista è equivalente a

for sublist in mylist: 
    for elem in sublist 

e genera una lista che dove 'd' può essere testato contro il 012.operatore.

+1

Solo per capire cosa sta succedendo puoi chiarire cosa sono io e io? – fdsa

+0

@fdsa Aggiornerò la mia risposta aggiungendo una versione "verbose" (nomi di variabili più descrittive) – Levon

+0

Grazie per aver dedicato del tempo, lo apprezzo – fdsa

3

utilizzare un'espressione generatore, qui la lista non verrà spostato come generatore generare risultati uno per uno:

>>> lis = [['a','b','c'],['d','e','f']] 
>>> 'd' in (y for x in lis for y in x) 
True 
>>> gen = (y for x in lis for y in x) 
>>> 'd' in gen 
True 
>>> list(gen) 
['e', 'f'] 

~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in (y for x in lis for y in x)" 
    100000 loops, best of 3: 2.96 usec per loop 

~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in [y for x in lis for y in x]" 
    100000 loops, best of 3: 7.4 usec per loop 
+0

Cosa intendi con "l'intera lista non verrà attraversata"? .. non finisci presto, devi generare tutti i valori ad un certo punto, no? La formulazione sembra implicare il contrario. – Levon

+0

@Levon ma non genera 'e' e' f'. –

+1

Quindi si comporta come un'espressione booleana in cortocircuito? Non lo sapevo .. pulito. Grazie, ho imparato qualcosa di nuovo. – Levon

2

Se gli array vengono sempre ordinati come mostrato, in modo che a[i][j] <= a[i][j+1] e a[i][-1] <= a[i+1][0] (l'ultimo elemento di un array sia sempre minore o uguale al primo elemento nell'array successivo), è possibile eliminare molti confronti facendo qualcosa di simile:

a = # your big array 

previous = None 
for subarray in a: 
    # In this case, since the subarrays are sorted, we know it's not in 
    # the current subarray, and must be in the previous one 
    if a[0] > theValue: 
     break 
    # Otherwise, we keep track of the last array we looked at 
    else: 
     previous = subarray 

return (theValue in previous) if previous else False 

Questo tipo di ottimizzazione è utile solo se si hanno un sacco di array e tutti hanno un sacco di elementi però.

+0

Grazie per questo - non avevo pensato di ordinarli ma saranno usati abbastanza spesso, quindi prenderò in considerazione l'ordinamento – fdsa

+0

Nessun problema - Non so quanti dati avete o che cosa utilizzerete esattamente è, ma se hai molti dati potrebbe valere la pena di esaminare il modulo python [collections] (http://docs.python.org/library/collections.html), che ha strutture dati ad alte prestazioni adatte a specifici compiti. –

+2

Sono sempre ordinati, sarebbe meglio usare il modulo 'bisect' –

9
>>> lis=[['a','b','c'],['d','e','f']] 
>>> any('d' in x for x in lis) 
True 

espressione generatore utilizzando any

$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "any('d' in x for x in lis)" 
1000000 loops, best of 3: 1.32 usec per loop 

generatore di espressione

$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in (y for x in lis for y in x)" 
100000 loops, best of 3: 1.56 usec per loop 

di lista

$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in [y for x in lis for y in x]" 
100000 loops, best of 3: 3.23 usec per loop 

Che ne dici se l'elemento è vicino alla fine o non è presente affatto? any è più veloce rispetto alla lista di comprensione

$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" 
    "'NOT THERE' in [y for x in lis for y in x]" 
100000 loops, best of 3: 4.4 usec per loop 

$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" 
    "any('NOT THERE' in x for x in lis)" 
100000 loops, best of 3: 3.06 usec per loop 

Forse, se la lista è 1000 volte più a lungo?any è ancora più veloce

$ python -m timeit -s "lis=1000*[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" 
    "'NOT THERE' in [y for x in lis for y in x]" 
100 loops, best of 3: 3.74 msec per loop 
$ python -m timeit -s "lis=1000*[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" 
    "any('NOT THERE' in x for x in lis)" 
100 loops, best of 3: 2.48 msec per loop 

Sappiamo che i generatori prendere un po 'di impostare, in modo dalle migliori possibilità per la LC per vincere è un breve elenco

$ python -m timeit -s "lis=[['a','b','c']]" 
    "any('c' in x for x in lis)" 
1000000 loops, best of 3: 1.12 usec per loop 
$ python -m timeit -s "lis=[['a','b','c']]" 
    "'c' in [y for x in lis for y in x]" 
1000000 loops, best of 3: 0.611 usec per loop 

E any usa meno memoria troppo

+0

Sarei cauto generalizzare su questo basato sulla ricerca di ''d'' (cioè qualcosa relativamente vicino al fronte della lista).Se guardate la discussione @Ashwini e ho avuto (sotto la sua risposta) vedrete che la scelta del "target" nella lista fa una differenza significativa. Nelle nostre prove LC ha battuto il generatore con bersagli nel mezzo e alla fine. Il generatore "ha vinto" se l'obiettivo era vicino al fronte. Penso che alla fine tutto dipenda molto dal set di dati e dall'obiettivo ricercati. – Levon

+0

@Levon, sono a conoscenza dei compromessi. Comunque in questo caso, 'any' è ancora più veloce del LC anche se l'oggetto non è affatto presente. –

+0

Non volevo insinuare che tu non fossi .. e l'uso di 'any' non mi è mai venuto in mente fino a quando non l'hai inventato, quindi è qualcosa che devo tenere a mente per un uso futuro. – Levon

Problemi correlati