Reputation: 402
I have a list of strings a, and a list of tuples b where:
a=['from src1 to dest2','from src3 to dest4','from src5 to dest6']
b=[['destb','dest2'],['destd','loc4'],['destf','dest6'],['desth','dest8']]
a and b can vary in length and be unequal.
I want to iterate through a, check if 'dest' matches the first string in each tuple, replacing it with the second string if it does, and append it to a new list. If no match is found, I want to append the string unchanged to the list.
So it should look something like this:
newlist=['from src1 to destb','from src3 to destd','from src5 to destf']
My current code looks like this:
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)
As expected, this repeatedly appends the currently iterated source_dest_statement when there are no matches, when I need them to only occur as many times as they were present in the original list. What would be the simplest way to fix this behaviour?
EDIT: I'll try to explain the problem I'm trying to solve:
I have a firewall config which has a number of NAT statements. These statements have changed in the updated version of code, so where destination addresses used mapped addresses, they now use real addresses instead.
My list of tuples is a list of real address to mapped address pairs. So something like [(realaddress1,mappedaddress1),(r2,m2),(r3,m3)] and so on.
I have the old access list rulebase which I want to go through, and replace all the references to the mapped addresses with the corresponding real address.
What I'm trying to do:
Upvotes: 3
Views: 221
Reputation: 90909
EDIT :
Since you say -
Each tuple in the list of tuples needs to be searched for in the whole list of source/dest statements.
You can add the element to the result list and then keep replacing inside it as you find elements in it from the tuple. Example -
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])
Demo -
>>> 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']
PREVIOUS ANSWER :
This is what the for..else
construct is for.
You can add the statement to add the not-changed source_dest_statement
into amended_source_dest_statements
, in the else:
part of the for
loop. And in the if
part inside the second for
loop, you can break
once you find a match and add the changed result to the list.
The else
part of a for
loop is only executed if you exit the for
loop normally, without using a break
statement, hence that would be the case when you don't find any matches. Example -
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)
Also, as explained in comments, b
is not a list of tuples, its a list of lists (Though does not really matter for your particular usecase).
Demo -
>>> 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']
Upvotes: 1
Reputation: 672
If the destination in a is found in b[0], b[1] is substituted into a and the new string is added to the result. If no substitutions we're done it outputs the original instead.
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)
On your test input it outputs this:
['from src1 to destb', 'from src3 to locd', 'from src5 to destf']
Upvotes: 1