Reputation: 925
I have a tuple that looks like this
full = [('Ethernet4/3', 'odsa', 'connected'),('Port-Channel161', 'odsa', 'connected'),('Port-Channel545', 'odsa', 'connected')]
I want to remove all the Port-Channels to return only the interfaces. I can hard code each Port-Channel in a list and remove it that way, but that isn't very scalable. I'm trying to remove anything with 'Port' in it from a list, so my script looks like this
full = [('Ethernet4/3', 'odsa', 'connected'),('Port-Channel161', 'odsa', 'connected')]
skip_interfaces = ['Ethernet49/1', 'Ethernet49/2', 'Ethernet49/3', 'Ethernet49/4', 'Ethernet50/1', 'Ethernet50/2', 'Ethernet50/3','Ethernet50/4','Ethernet51/1',
'Ethernet51/2', 'Ethernet51/3', 'Ethernet51/4', 'Ethernet52/1', 'Ethernet52/2', 'Ethernet52/3', 'Ethernet52/4', 'Port', 'Management1', 'Port-Channel44', 'Port-Channel34']
new = [tup for tup in full if tup[0] not in skip_interfaces]
print new
But when printed i still get
[('Ethernet4/3', 'odsa', 'connected'),('Port-Channel161', 'odsa', 'connected'),('Port-Channel545', 'odsa', 'connected')]
Is there a better way to remove items from a tuple when a substring is in a list?
Thanks
Upvotes: 3
Views: 846
Reputation: 402834
You can use str.startswith
to filter out all tuples whose first element begins with "Port", or "Port-Channel", using a list comprehension. str.startwsith
can be used in conjunction with a couple of alternatives, listed below.
Option 1
list comprehension
>>> [i for i in full if not i[0].startswith('Port')] # .startswith('Port-Channel')
[('Ethernet4/3', 'odsa', 'connected')]
Alternatively, you can perform a not in
check on i[0]
, which will filter elements based on whether i[0]
contains "Port" anywhere.
>>> [i for i in full if 'Port' not in i[0]]
[('Ethernet4/3', 'odsa', 'connected')]
Option 2
vanilla for
loop
A second approach (very similar to the first) is using a plain ol' for
loop. Iterate over full
and make a check with an if
clause.
r = []
for i in full:
if not i[0].startswith('Port'):
r.append(i)
Option 3
filter
filter
is another alternative here. The filter
removes elements which do not conform to a particular condition. The condition here is the first argument, passed as a lambda
. The second argument is the list to be filtered.
>>> list(filter(lambda x: not x[0].startswith('Port'), full))
[('Ethernet4/3', 'odsa', 'connected')]
filter
is generally slower, compared to a list comprehension. Still a useful construct for concise code, and chaining more expressions in a larger pipeline.
Note: You should never iterate over a list with a loop and remove elements in place, using methods such as remove
and del
. This would result in your list shrinking, and the end result is that the loop will not have the chance to completely iterate over the list elements.
Upvotes: 6