Python so sánh nhiều danh sách

Sep 17 2020

Tôi có một số mã có ba danh sách và sau đó nó sẽ kiểm tra chỉ mục của danh sách thứ hai so với chỉ mục của danh sách đầu tiên miễn là danh sách đầu tiên có sáu phần tử. Sau đó, mã sẽ thêm vào danh sách thứ ba nếu một phần của chuỗi khớp với chỉ mục của danh sách đầu tiên. Nếu chuỗi không khớp, nó sẽ nối thêm một thông báo. Tôi hy vọng sẽ tìm ra một cách tốt hơn, nhiều hơn Pythonic để viết thuật toán của mình. Đây là mã của tôi:

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

Mã này hoạt động cho những gì tôi muốn nó làm nhưng tôi nghĩ nó quá dài. Bất kỳ sự giúp đỡ nào trong việc làm cho mã này nhiều hơn Pythonic sẽ được đánh giá rất cao. Cảm ơn trước.

Trả lời

2 FMc Sep 18 2020 at 00:11

Đánh giá của tôi về mã hiện tại của bạn rất dễ tóm tắt: Nó quá phức tạp và khiến tôi đau đầu . Nhưng đừng cảm thấy tồi tệ, bởi vì bạn đang ở trong một công ty tuyệt vời. Những nỗ lực đầu tiên thường như vậy - ngay cả với những người đã làm việc này trong một thời gian dài.

Cụ thể là điều gì khiến bạn khó hiểu? Độ phức tạp của thuật toán: các vòng lặp và điều kiện lồng nhau, ngắt, quản lý chỉ mục danh sách, v.v. Bất cứ khi nào bạn nhận thức được loại phức tạp đó, bạn thường cân nhắc xem liệu một cấu trúc dữ liệu mạnh mẽ hơn có đơn giản hóa tình hình hay không (Tôi đang sử dụng "cấu trúc dữ liệu" theo nghĩa rất rộng). Trong phần viết lại được cung cấp bên dưới, chúng tôi sẽ sử dụng một giá trị có thể lặp lại đặc biệt cho phép chúng tôi xem qua giá trị tiếp theo mà không thực sự sử dụng nó mỗi lần. Một thay đổi đó đơn giản hóa đáng kể việc ghi sổ bên trong vòng lặp chính và nó cũng đơn giản hóa cách chúng tôi nối phần còn lại cần thiết của các giá trị bị thiếu sau khi chúng tôi thoát khỏi vòng lặp.

# 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

Vì continueluôn xảy ra ở cuối vòng lặp, bạn có thể đảo ngược các điều kiện này để làm cho nó ngắn hơn.

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

bây giờ bạn không cần elsevì bất cứ điều gì khác ngoài điều kiện nghỉ sẽ continuetự động.

Cao hơn nơi bạn đặt cont = False, bạn có thể sử dụng breakthay thế theo như tôi có thể nói. Điều đó loại bỏ nhu cầu conthoàn toàn để bạn có thể làmwhile True:

GáborFekete Sep 17 2020 at 23:37

Tôi chủ yếu trả lời trên SO vì vậy câu trả lời của tôi có thể không tuân theo PEP8 hoặc các nguyên tắc khác nhưng tôi đã cố gắng tạo phiên bản mã của bạn dễ dàng hơn để xem những gì đang xảy ra, không có dấu ngắt, tiếp tục và có số dòng nhỏ hơn:

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