Reputation: 1489
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
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
Reputation: 49330
With these list
s:
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