簡體   English   中英

Python:將字符串列表與元組列表進行比較,並根據匹配或不匹配創建新列表

[英]Python: Compare list of strings to list of tuples, and create a new list based on match or no match

我有一個字符串列表a和一個元組列表b,其中:

a=['from src1 to dest2','from src3 to dest4','from src5 to dest6']
b=[['destb','dest2'],['destd','loc4'],['destf','dest6'],['desth','dest8']]

a和b的長度可以不同並且不相等。

我想迭代一遍,檢查'dest'是否與每個元組中的第一個字符串匹配,如果是,則將其替換為第二個字符串,並將其附加到新列表中。 如果找不到匹配項,我想將字符串不加改變地附加到列表中。

所以看起來應該是這樣的:

newlist=['from src1 to destb','from src3 to destd','from src5 to destf']

我當前的代碼如下所示:

for source_dest_statement in source_dest_statements:
  for i,j in in source_dest_tuple:
    if j in source_dest_statement:
      amended_source_dest_statements.append('SOMETHING HAS CHANGED!')
      amended_source_dest_statements.append(re.sub(j,i,source_dest_statement))
    else:
      amended_source_dest_statements.append(source_dest_statement)

正如預期的那樣,當沒有匹配時,這會反復追加當前迭代的source_dest_statement,當我需要它們只出現在原始列表中的次數時。 解決此問題的最簡單方法是什么?

編輯:我會嘗試解釋我試圖解決的問題:

我有一個防火牆配置,它有許多NAT語句。 這些語句在更新的代碼版本中已更改,因此在目標地址使用映射地址的情況下,它們現在使用實際地址。

我的元組列表是映射地址對的實際地址列表。 所以像[(realaddress1,mappedaddress1),(r2,m2),(r3,m3)]等等。

我有舊的訪問列表規則庫,我想通過,並用相應的實際地址替換映射地址的所有引用。

我正在嘗試做什么: - 迭代訪問列表規則。 - 如果找到映射的地址匹配,則修改規則,附加到列表,插入注釋,說明規則已被修改。 - 如果未找到匹配項,請將現有規則附加到列表中。

編輯 - 解決方案

for / else語句解決了我的問題。 因此它看起來像這樣:對於某些列表中的currline:對於i,j在sometuple中:如果j在currline中:newlistoflines.append(re.sub(j,i,currline))break else:newlistoflines.append(currline)

感謝您的幫助! 我現在知道break語句不是邪惡的東西,但我仍然想知道是否有更優雅的方法來解決我的問題。

編輯:

既然你說 -

需要在整個source / dest語句列表中搜索元組列表中的每個元組。

您可以將元素添加到結果列表中,然后在元組中找到元素時繼續替換它。 示例 -

for source_dest_statement in source_dest_statements:
    amended_source_dest_statements.append(source_dest_statement)
    for i,j in in source_dest_tuple:
        if j in amended_source_dest_statements[-1]:
            amended_source_dest_statements[-1]   = re.sub(j,i,amended_source_dest_statements[-1])

演示 -

>>> import re
>>> a=['from src1 to dest2','from src3 to dest4','from src5 to dest6']
>>> b=[['destb','dest2'],['destd','loc4'],['destf','dest6'],['desth','dest8']]
>>> result = []
>>> for x in a:
...     result.append(x)
...     for i,j in b:
...             if j in result[-1]:
...                     result[-1] = re.sub(j,i,result[-1])
...
>>> result
['from src1 to destb', 'from src3 to dest4', 'from src5 to destf']

以前的答案:

這就是for..else結構的用途。

您可以在for循環的else:部分中添加語句以將未更改的source_dest_statement添加到amended_source_dest_statements中。 在第二個for循環內的if部分中,一旦找到匹配就可以break ,並將更改后的結果添加到列表中。

for循環的else部分僅在正常退出for循環時執行,而不使用break語句,因此當您沒有找到任何匹配時就是這種情況。 示例 -

for source_dest_statement in source_dest_statements:
    for i,j in in source_dest_tuple:
        if j in source_dest_statement:
            amended_source_dest_statements.append(re.sub(j,i,source_dest_statement))
    else:
        amended_source_dest_statements.append(source_dest_statement)

另外,正如注釋中所解釋的那樣, b不是元組列表,它是列表列表(雖然對於您的特定用例並不重要)。

演示 -

>>> a=['from src1 to dest2','from src3 to dest4','from src5 to dst6']
>>> b=[['dest2','destb'],['dest4','locd'],['dest6','destf'],['dest8','desth']]
>>> result = []
>>> for x in a:
...     for i,j in b:
...         if i in x:
...             result.append(re.sub(i,j,x))
...             break
...     else:
...         result.append(x)
...
>>> result
['from src1 to destb', 'from src3 to locd', 'from src5 to dst6']

如果在b [0]中找到a中的目的地,則將b [1]代入a,並將新字符串添加到結果中。 如果我們沒有完成替換,則輸出原始代替。

result = []
for source in a:
    # Do all replacements with a list-comprehension
    replacements = [source.replace(old,new) for old, new in b if old in source]
    # If replacements we're done add the replacements else add the source
    if replacements:
        result.extend(replacements)
    else:
        result.append(source)

在您的測試輸入上,它輸出:

['from src1 to destb', 'from src3 to locd', 'from src5 to destf']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM