繁体   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