Çoklu liste karşılaştırması Python

Sep 17 2020

Üç listeli bir kodum var ve daha sonra, ilk liste altı öğeye sahip olduğu sürece, ikinci listenin dizinini birinci listenin diziniyle karşılaştırarak kontrol ediyor. Bir dizenin bir bölümü ilk listenin diziniyle eşleşirse, kod üçüncü listeye eklenir. Dize eşleşmezse, bir mesaj ekleyecektir. Algoritmamı yazmanın daha iyi, daha Pythonic yolunu bulmayı umuyorum. İşte kodum:

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

Bu kod benim yapmasını istediğim şey için çalışıyor ama bence çok uzun. Bu kodu daha Pythonic yapmak için herhangi bir yardım çok takdir edilecektir. Şimdiden teşekkürler.

Yanıtlar

2 FMc Sep 18 2020 at 00:11

Mevcut kodunuzla ilgili incelememin özetlenmesi kolaydır: Çok karmaşık ve başımı ağrıttı . Ama kendinizi kötü hissetmeyin çünkü harika bir şirketsiniz. İlk girişimler genellikle böyledir - bunu uzun süredir yapan insanlar için bile.

Özellikle anlamayı zorlaştıran nedir? Algoritmik karmaşıklık: iç içe geçmiş döngüler ve koşul ifadeleri, kesmeler, liste dizinlerini yönetme vb. Bu tür bir karmaşıklığı algıladığınızda, genellikle daha güçlü bir veri yapısının durumu basitleştirip basitleştirmeyeceğini düşünmek yardımcı olur ("veri yapısını" çok geniş anlamda kullanıyorum). Aşağıda sunulan yeniden yazımda, her seferinde onu gerçekten tüketmeden bir sonraki değere göz atmamızı sağlayan özel bir yinelenebilirlik kullanacağız. Bu tek değişiklik, ana döngü içindeki defter tutmayı büyük ölçüde basitleştirir ve ayrıca döngüden çıktıktan sonra gerekli kalan eksik değerleri nasıl ekleyeceğimizi basitleştirir.

# 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)
1 user985366 Sep 17 2020 at 19:46
if c < len(L2):
    continue
else:
    c = 0
    break

Yana continuehep bir döngü sonunda olur, bunu kısaltmak için, bu koşulları tersine çevirebilir.

if c >= len(L2):
    c = 0
    break

elsekırılma durumu dışında herhangi bir şey continueotomatik olarak gerçekleşeceği için artık ihtiyacınız yok .

Ayarladığınız yerden daha yükseğe cont = False, breaksöyleyebileceğim kadarıyla onun yerine kullanabilirsiniz . Bu, ihtiyacınızı conttamamen ortadan kaldırır, böylece sadece yapabilirsinizwhile True:

GáborFekete Sep 17 2020 at 23:37

Çoğunlukla SO'ya cevap veriyorum, bu yüzden cevabım PEP8'i veya diğer yönergeleri takip etmiyor olabilir, ancak kodunuzun, ifler, kesintiler, devam eden ve daha küçük bir satır sayısına sahip, neler olup bittiğini görmek için daha kolay bir versiyonunu yapmaya çalıştım:

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