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 的长度可以不同并且不相等。
我想遍历 a,检查 '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 语句解决了我的问题。所以它看起来像这样:
对于 somelist 中的 currline:
对于某个元组中的 i,j:
如果 j 在 currline 中:
newlistoflines.append(re.sub(j,i,currline))
休息
别的:
newlistoflines.append(曲线)
感谢大家的帮助!我现在知道 break 语句不是什么坏东西,但我仍然想知道是否有更优雅的方法来解决我的问题。
编辑:
既然你说 -
Each tuple in the list of tuples needs to be searched for in the whole list of source/dest statements.
您可以将元素添加到结果列表中,然后在从元组中找到其中的元素时继续在其中进行替换。例子-
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']
如果a中的目的地在b[0]中找到,则将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']
我有一个字符串列表 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 的长度可以不同并且不相等。
我想遍历 a,检查 '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 语句解决了我的问题。所以它看起来像这样: 对于 somelist 中的 currline: 对于某个元组中的 i,j: 如果 j 在 currline 中: newlistoflines.append(re.sub(j,i,currline)) 休息 别的: newlistoflines.append(曲线)
感谢大家的帮助!我现在知道 break 语句不是什么坏东西,但我仍然想知道是否有更优雅的方法来解决我的问题。
编辑:
既然你说 -
Each tuple in the list of tuples needs to be searched for in the whole list of source/dest statements.
您可以将元素添加到结果列表中,然后在从元组中找到其中的元素时继续在其中进行替换。例子-
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']
如果a中的目的地在b[0]中找到,则将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']