Porównanie wielu list Python
Mam kod, który ma trzy listy, a następnie sprawdza indeks drugiej listy względem indeksu pierwszej, o ile pierwsza lista ma sześć elementów. Kod zostanie następnie dołączony do trzeciej listy, jeśli część ciągu pasuje do indeksu pierwszej listy. Jeśli ciąg nie pasuje, dołączy wiadomość. Mam nadzieję, że znajdę lepszy, bardziej Pythonowy sposób pisania mojego algorytmu. Oto mój kod:
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
Ten kod działa zgodnie z tym, co chcę, ale myślę, że jest za długi. Każda pomoc w uczynieniu tego kodu bardziej Pythonic będzie bardzo mile widziana. Z góry dziękuję.
Odpowiedzi
Moją recenzję twojego obecnego kodu łatwo podsumować: jest cholernie skomplikowany i boli mnie głowa . Ale nie czuj się źle, bo jesteś w świetnym towarzystwie. Często takie są pierwsze próby - nawet dla osób, które robią to od dłuższego czasu.
Co konkretnie utrudnia zrozumienie? Złożoność algorytmiczna: zagnieżdżone pętle i instrukcje warunkowe, przerwy, zarządzanie indeksami list i tak dalej. Ilekroć dostrzegasz tego rodzaju złożoność, często warto zastanowić się, czy potężniejsza struktura danych uprościłaby sytuację (używam „struktury danych” w bardzo szerokim znaczeniu). W poniższym przepisaniu użyjemy specjalnej iteracji, która pozwoli nam zerknąć na następną wartość bez faktycznego jej zużywania za każdym razem. Ta jedna zmiana drastycznie upraszcza prowadzenie ksiąg w głównej pętli, a także upraszcza sposób, w jaki dodajemy resztę brakujących wartości po wyjściu z pętli.
# 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
Ponieważ continuezawsze dzieje się na końcu pętli, możesz odwrócić te warunki, aby ją skrócić.
if c >= len(L2):
c = 0
break
teraz nie potrzebujesz, elseponieważ cokolwiek innego niż stan zerwania będzie continueautomatycznie.
Wyżej, gdzie się usiadłeś cont = False, możesz użyć breakzamiast tego, o ile wiem. To contcałkowicie eliminuje potrzebę, więc możesz to zrobićwhile True:
Odpowiadam głównie na SO, więc moja odpowiedź może nie być zgodna z PEP8 lub innymi wytycznymi, ale próbowałem stworzyć wersję twojego kodu, która będzie łatwiejsza do zobaczenia, bez ifs, break, kontynuacji i mającej mniejszą liczbę linii:
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