Perbandingan beberapa daftar Python

Sep 17 2020

Saya memiliki beberapa kode yang memiliki tiga daftar, dan kemudian memeriksa indeks daftar kedua terhadap indeks yang pertama selama daftar pertama memiliki enam elemen. Kode kemudian akan ditambahkan ke daftar ketiga jika bagian dari string cocok dengan indeks dari daftar pertama. Jika string tidak cocok, itu akan menambahkan pesan. Saya berharap menemukan cara yang lebih baik, lebih Pythonic dalam menulis algoritme saya. Ini kode saya:

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

Kode ini berfungsi untuk apa yang saya inginkan, tetapi menurut saya kode ini terlalu panjang. Bantuan apa pun dalam membuat kode ini lebih Pythonic akan sangat dihargai. Terima kasih sebelumnya.

Jawaban

2 FMc Sep 18 2020 at 00:11

Ulasan saya tentang kode Anda saat ini mudah untuk diringkas: Ini terlalu rumit dan membuat kepala saya sakit . Tapi jangan merasa buruk, karena Anda berada di perusahaan yang hebat. Upaya pertama seringkali seperti itu - bahkan untuk orang yang telah melakukan ini sejak lama.

Secara khusus, apa yang membuatnya sulit untuk dipahami? Kompleksitas algoritme: loop dan kondisional bersarang, break, mengelola indeks daftar, dan sebagainya. Kapan pun Anda melihat jenis kerumitan itu, sering kali membantu untuk mempertimbangkan apakah struktur data yang lebih kuat akan menyederhanakan situasi (saya menggunakan "struktur data" dalam arti yang sangat luas). Dalam penulisan ulang yang ditawarkan di bawah ini, kita akan menggunakan iterable khusus yang memungkinkan kita mengintip nilai berikutnya tanpa benar-benar mengonsumsinya setiap saat. Perubahan itu secara drastis menyederhanakan pembukuan di dalam loop utama, dan ini juga menyederhanakan bagaimana kita menambahkan sisa nilai yang hilang setelah kita keluar dari loop.

# 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

Karena continueselalu terjadi di akhir pengulangan, Anda dapat membalikkan kondisi ini, untuk membuatnya lebih pendek.

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

sekarang Anda tidak perlu elsekarena apa pun selain kondisi istirahat akan continuesecara otomatis.

Lebih tinggi di mana Anda mengatur cont = False, Anda bisa menggunakan breaksebagai gantinya sejauh yang saya tahu. Itu menghilangkan kebutuhan contsama sekali sehingga Anda bisa melakukannyawhile True:

GáborFekete Sep 17 2020 at 23:37

Saya sebagian besar menjawab di SO jadi jawaban saya mungkin tidak mengikuti PEP8 atau pedoman lain tetapi saya mencoba membuat versi kode Anda yang lebih mudah untuk melihat apa yang terjadi, tanpa jika, jeda, berlanjut dan memiliki jumlah baris yang lebih kecil:

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