複数リスト比較Python

Sep 17 2020

3つのリストを持つコードがあり、最初のリストに6つの要素がある限り、2番目のリストのインデックスを最初のリストのインデックスと照合します。文字列の一部が最初のリストのインデックスに一致する場合、コードは3番目のリストに追加されます。文字列が一致しない場合は、メッセージが追加されます。私は自分のアルゴリズムを書くためのより良い、よりPythonicな方法を見つけたいと思っています。これが私のコードです:

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

このコードは私がやりたいことのために機能しますが、長すぎると思います。このコードをよりPythonicにするための助けをいただければ幸いです。前もって感謝します。

回答

2 FMc Sep 18 2020 at 00:11

あなたの現在のコードの私のレビューは簡単に要約できます:それは非常に複雑で、私の頭を傷つけます。しかし、あなたは素晴らしい仲間にいるので、気分が悪くなることはありません。最初の試みは、多くの場合、そのようなものです–これを長い間行ってきた人々にとってさえ。

具体的には、何がわかりにくいのでしょうか。アルゴリズムの複雑さ:ネストされたループと条件、ブレーク、リストインデックスの管理など。この種の複雑さを感じるときはいつでも、より強力なデータ構造が状況を単純化するかどうかを検討するのに役立つことがよくあります(私は非常に広い意味で「データ構造」を使用しています)。以下に示す書き直しでは、毎回実際に消費することなく次の値を覗くことができる特別な反復可能オブジェクトを使用します。この1つの変更により、メインループ内の簿記が大幅に簡素化され、ループを終了した後に必要な残りの欠落値を追加する方法も簡素化されます。

# 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

以来continue、常にループの終わりに起こる、あなたはそれを短くするために、これらの条件を逆にすることができます。

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

elseブレーク条件以外はcontinue自動的に行われるため、今は必要ありません。

設定した場所の上の方でcont = False、break私が知る限り、代わりに使用できます。それはcontあなたがただすることができるように完全に必要性を取り除きますwhile True:

GáborFekete Sep 17 2020 at 23:37

私は主にSOで回答しているので、私の回答はPEP8または他のガイドラインに従わない可能性がありますが、if、breaks、continueを使用せず、行数を減らして、何が起こっているのかを簡単に確認できるバージョンのコードを作成しようとしました。

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