Lucas Aimaretto
Lucas Aimaretto

Reputation: 1489

Searching items in two lists

I have two lists in python such as:

List1:

('C2244_LNO70_SARM', '1/1/2', '1/2/8', 'CF164_LUJ70_SAR8', 'Router')
('C1723_LN270_SARM', '1/1/1', '1/1/8', 'CF164_LUJ70_SAR8', 'Router')
('CF618_JURI70_SARM', '1/1/1', '1/2/7', 'CF164_LUJ70_SAR8', 'Router')
('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router')
('C2335_ODR70_SARM', '1/1/2', '1/1/2', 'CF693_LAC70_SARM', 'Router')

List2:

('CF618_JURI70_SARM')
('C2335_ODR70_SARM')
('CF617_LJ370_SARM')

Now, I want to walk along List1 in such a way that if the values of column0 or column3 do not exist in List2, then that record shall be removed.

For example, in List1(4,3), value CF693_LAC70_SARM does not exist in List2. Then row 4 could be removed from List1.

What's the best way of doing it? I tried nesting two for-loops with if-else conditions but I cannot achieve it ...

Any hint is appreciated...

Lucas

Upvotes: 2

Views: 82

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180522

Use a set to store all the strings from the tuples in list2 and check if either subelement from each tuple is in the set:

l1=[('C2244_LNO70_SARM', '1/1/2', '1/2/8', 'CF164_LUJ70_SAR8', 'Router'),
('C1723_LN270_SARM', '1/1/1', '1/1/8', 'CF164_LUJ70_SAR8', 'Route'),
('CF618_JURI70_SARM', '1/1/1', '1/2/7', 'CF164_LUJ70_SAR8', 'Router'),
('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router'),
('C2335_ODR70_SARM', '1/1/2', '1/1/2', 'CF693_LAC70_SARM', 'Router')]

l2 = [('CF618_JURI70_SARM',),
('C2335_ODR70_SARM',),
('CF617_LJ370_SARM',)]

st = {t[0] for t in l2 }

# update original list
l1[:] = [t for t in l1 if t[0] in st or t[3] in st]

print(l1)

Output:

[('CF618_JURI70_SARM', '1/1/1', '1/2/7', 'CF164_LUJ70_SAR8', 'Router'), ('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router'), ('C2335_ODR70_SARM', '1/1/2', '1/1/2', 'CF693_LAC70_SARM', 'Router')]

I presume you mean index 0 and index 3 which are the first and fourth columns.

If both ele 0 and ele 3 have to exist then use and:

l1[:] = [t for t in l1 if t[0] in st and t[3] in st]

which would leave a single tuple which is the fourth:

[('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router')]

You can also use set.issuperset which tests whether every element in t is in s:

l1[:] = [t for t in l1 if st.issuperset([t[0],t[3]])]

print((l1))

Which again would leave just the one tuple:

[('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router')]

Once your data is any reasonable size the cost of building the set will be offset by the efficient 0(1) lookups that a set provides so your code will be 0(n) as opposed to quadratic just using lists.

Upvotes: 3

TigerhawkT3
TigerhawkT3

Reputation: 49330

With these lists:

List1 = [('C2244_LNO70_SARM', '1/1/2', '1/2/8', 'CF164_LUJ70_SAR8', 'Router'),
('C1723_LN270_SARM', '1/1/1', '1/1/8', 'CF164_LUJ70_SAR8', 'Router'),
('CF618_JURI70_SARM', '1/1/1', '1/2/7', 'CF164_LUJ70_SAR8', 'Router'),
('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router'),
('C2335_ODR70_SARM', '1/1/2', '1/1/2', 'CF693_LAC70_SARM', 'Router')]
List2 = [('CF618_JURI70_SARM'),
('C2335_ODR70_SARM'),
('CF617_LJ370_SARM')]

You can use the in operator to filter out the unwanted results:

filtered_list = [item for item in List1 if item[0] in List2 and item[3] in List2]

Or set operations:

List2s = set(List2)
filtered_list = [item for item in List1 if len({item[0], item[3]} & List2s) == 2]

In either case, this leaves us with:

>>> print(*filtered_list, sep='\n')
('CF618_JURI70_SARM', '1/1/2', '1/1/1', 'CF617_LJ370_SARM', 'Router')

Upvotes: 1

Related Questions