Ho una lista di comprensione che assomiglia a questo:Ottenere tutte le chiavi in un dict che si sovrappongono ad altri tasti nella stessa dict
cart = [ ((p,pp),(q,qq)) for ((p,pp),(q,qq))\
in itertools.product(C.items(), repeat=2)\
if p[1:] == q[:-1] ]
C
è un dict con le chiavi che sono tuple di interi arbitrari. Tutte le tuple hanno la stessa lunghezza. Il caso peggiore è che tutte le combinazioni dovrebbero essere incluse nella nuova lista. Questo può accadere abbastanza frequentemente.
Per fare un esempio, ho un dizionario come questo:
C = { (0,1):'b',
(2,0):'c',
(0,0):'d' }
E voglio che il risultato sia:
cart = [ (((2, 0), 'c'), ((0, 1), 'b'))
(((2, 0), 'c'), ((0, 0), 'd'))
(((0, 0), 'd'), ((0, 1), 'b'))
(((0, 0), 'd'), ((0, 0), 'd')) ]
Così, si sovrappongono mi riferisco, per esempio, che le tuple (1,2,3,4)
e (2,3,4,5)
hanno la sezione di sovrapposizione (2,3,4). Le sezioni sovrapposte devono essere sui "bordi" delle tuple. Voglio solo sovrapposizioni che abbiano una lunghezza inferiore alla lunghezza della tupla. Pertanto, (1,2,3,4)
non si sovrappone a (3,4,5,6)
. Si noti inoltre che quando si rimuove il primo o l'ultimo elemento di una tupla potremmo finire con tuple non distinte, che devono essere confrontate con tutti gli altri elementi. Questo ultimo punto non è stato enfatizzato nel mio primo esempio.
La parte migliore del tempo di esecuzione dei miei codici viene utilizzata per comprendere questo elenco. Ho sempre bisogno di tutti gli elementi di cart
quindi non sembra esserci alcuna accelerazione quando si utilizza un generatore.
La mia domanda è: c'è un modo più veloce per farlo?
un pensiero che avevo era che avrei potuto cercare di creare due nuovi dizionari come questo:
aa = defaultdict(list)
bb = defaultdict(list)
[aa[p[1:]].append(p) for p in C.keys()]
[bb[p[:-1]].append(p) for p in C.keys()]
E in qualche modo unire tutte le combinazioni di elementi della lista in aa[i]
con l'elenco in bb[i]
per tutti i
, ma Nemmeno io riesco a comprendere questa idea.
Aggiornamento
Sia la soluzione aggiunto da tobias_k e shx2 hanno meglio la complessità del mio codice originale (per quanto posso dire). Il mio codice è O (n^2) mentre le altre due soluzioni sono O (n). Per la mia dimensione e composizione del problema, tuttavia, tutte e tre le soluzioni sembrano funzionare più o meno nello stesso tempo. Suppongo che questo abbia a che fare con una combinazione di sovraccarico associato alle chiamate di funzione, nonché la natura dei dati con cui lavoro. In particolare il numero di tasti diversi, così come la composizione effettiva dei tasti, sembra avere un grande impatto. Quest'ultimo lo so perché il codice funziona molto più lentamente per chiavi completamente casuali. Ho accettato la risposta di Tobias_k perché il suo codice è il più facile da seguire. Tuttavia, sarei ancora molto lieto di ricevere altri suggerimenti su come eseguire questa attività.
Non usare list comprehension per i loro effetti collaterali. Usa invece un ciclo for normale, c'è un costo per costruire una lista che stai scartando di nuovo. –
la prima versione del mio codice aveva un ciclo regolare per un 'continue' if' p [1:]! = Q [0: lvl] '. Questo è stato (con mia sorpresa) più lento del codice che ho fornito nella mia domanda. – inconvergent
puoi spiegare più chiaramente cosa deve fare il codice? forse mostrando alcuni semplici esempi? e a cosa serve il "* 2"? in particolare, sembra che tu stia mescolando chiavi e valori come se fossero lo stesso tipo di cosa, eppure non dica nulla sui valori. –