CEamonn
CEamonn

Reputation: 925

Remove items from tuple if substring exists

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

Answers (1)

cs95
cs95

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

Related Questions