Confronto di liste multiple Python
Ho un codice che ha tre elenchi, quindi controlla l'indice del secondo elenco rispetto all'indice del primo purché il primo elenco abbia sei elementi. Il codice verrà quindi aggiunto al terzo elenco se parte di una stringa corrisponde all'indice del primo elenco. Se la stringa non corrisponde, verrà aggiunto un messaggio. Spero di trovare un modo migliore e più pitonico di scrivere il mio algoritmo. Ecco il mio codice:
L1 = ["first = 1st","second = 2nd","third = 3rd","fourth = 4th","sixth = 6th",
"first = A","second = B","third = C","fifth = E","sixth = F",
"second = W","third = X","fourth = Y","fifth = Z","sixth = AA","first = BB"]
L2 = ["first","second","third","fourth","fifth","sixth"]
L3 = []
#Used in case a list has less than six elements
if len(L1) % 6 != 0:
L1.append("Missing_Data")
c = 0
for i in L1:
cont = True
while cont:
if L2[c] in i:
L3.append(i.split("= ")[-1])
c += 1
if c < len(L2):
cont = False
else:
c = 0
cont = False
else:
L3.append("Missing_Data")
c += 1
if c < len(L2):
continue
else:
c = 0
break
Questo codice funziona per quello che voglio che faccia, ma penso che sia troppo lungo. Qualsiasi aiuto nel rendere questo codice più Pythonic sarebbe molto apprezzato. Grazie in anticipo.
Risposte
La mia revisione del tuo codice attuale è facile da riassumere: è troppo complicato e mi fa male la testa . Ma non sentirti male, perché sei in ottima compagnia. I primi tentativi sono spesso così, anche per le persone che lo fanno da molto tempo.
Cosa, nello specifico, lo rende difficile da capire? Complessità algoritmica: cicli annidati e condizionali, interruzioni, gestione degli indici di elenchi e così via. Ogni volta che percepisci quel tipo di complessità, spesso aiuta a considerare se una struttura dati più potente semplificherebbe la situazione (sto usando "struttura dati" in un senso molto ampio). Nella riscrittura offerta di seguito, utilizzeremo uno speciale iterabile che ci consente di sbirciare il valore successivo senza consumarlo effettivamente ogni volta. Quella modifica semplifica drasticamente la contabilità all'interno del ciclo principale e semplifica anche il modo in cui aggiungiamo il resto necessario dei valori mancanti dopo essere usciti dal ciclo.
# This is a third party library that is worth knowing about.
from more_itertools import peekable
# Your data, aligned so we can see what is going on.
# When you ask a question, it's a good idea to help your helpers.
xs = [
'first = 1st', 'second = 2nd', 'third = 3rd', 'fourth = 4th', 'sixth = 6th',
'first = A', 'second = B', 'third = C', 'fifth = E', 'sixth = F',
'second = W', 'third = X', 'fourth = Y', 'fifth = Z', 'sixth = AA',
'first = BB',
]
ys = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
# Python has a builtin concept for missing data. Use it if you can.
# If you cannot, define a constant.
MISSING = None
# The results we want.
# When you ask a question, it's a good idea to provide this.
EXPECTED = [
'1st', '2nd', '3rd', '4th', MISSING, '6th',
'A', 'B', 'C', MISSING, 'E', 'F',
MISSING, 'W', 'X', 'Y', 'Z', 'AA',
'BB', MISSING, MISSING, MISSING, MISSING, MISSING
]
# We will use a peekable iterable for both the Xs and the Ys.
xit = peekable(xs)
yit = None
results = []
# Process all Xs to build the results.
# A Y is consumed each time, and we get a fresh Ys iterable as needed.
# We consume an X only when current X and Y agree.
while xit:
yit = yit or peekable(ys)
x = xit.peek()
y = next(yit)
val = next(xit).split('= ')[-1] if y in x else MISSING
results.append(val)
# The results should always contain a full cycle of Ys.
results.extend(MISSING for _ in yit)
# Check.
print(results == EXPECTED)
if c < len(L2):
continue
else:
c = 0
break
Dato che continueaccade sempre alla fine di un ciclo, puoi invertire queste condizioni, per renderlo più breve.
if c >= len(L2):
c = 0
break
ora non è necessario elsepoiché nient'altro che la condizione di interruzione verrà continueautomaticamente.
Più in alto dove ti sei ambientato cont = False, potresti usare breakinvece, per quanto posso dire. Ciò elimina la necessità di conttutto, quindi puoi semplicemente farlowhile True:
Sto principalmente rispondendo su SO, quindi la mia risposta potrebbe non seguire PEP8 o altre linee guida, ma ho provato a creare una versione del tuo codice che sia più facile da vedere cosa sta succedendo, senza se, interruzioni, continua e con un numero di righe inferiore:
length = len(L2)
missing = 'Missing_Data'
index = -1
for item in L1:
key,value = item.split(' = ')
current = L2.index(key)
no_missing = (current-index)%length-1 # get number of missing elements
L3 += [missing] * no_missing # append this many of the missing value
L3.append(value) # append current value
index = current
L3 += [missing] * (length-index-1) # fill rest of list with missing elements