Home > database >  Remove a dictionary from list if other list contains same dictionary
Remove a dictionary from list if other list contains same dictionary

Time:10-14

I am solving a specific problem and I would like to find out what is the most pythonic way. I have two list of dictionaries, for example:

l1 = [{id: '1', grade: 'A'}, {id: '2', grade: 'B'}, {id: '3', grade: 'A'}]
l2 = [{id: '1', grade: 'A'}, {id: '2', grade: 'B'}, {id: '3', grade: 'Unavailable'}]

There are always the same ids in boths lists, only the grades differ. Now I want to write a list comprehension to remove from l1 all the dictionaries that have Unavailable grade in l2. Meaning in this case I want to remove dict with id:3. Can someone help me out? Much thanks

CodePudding user response:

This works assuming l1 and l2 are of the same length. Try:

for dicIndex in range(len(l1)):
    if 'Unavailable' in l2[dicIndex].values():
        l1.pop(dicIndex)

print(l1)

Output:

[{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}]

CodePudding user response:

You could make an intermediate set of the ids you want to remove.

>>> l1 = [{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}, {'id': '3', 'grade': 'A'}]
>>> l2 = [{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}, {'id': '3', 'grade': 'Unavailable'}]
>>> unavailable = {g['id'] for g in l2 if g['grade'] == 'Unavailable'}
>>> l1_fixed = [g for g in l1 if g['id'] not in unavailable]
>>> l1_fixed
[{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}]

CodePudding user response:

You can do this with zip,

In [1]: [d1 for d1,d2 in zip(l1, l2) if d2.get('grade') != 'Unavailable']
Out[1]: [{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}]

If the list is not ordered so we need to sort before the list comprehension,

l1 = sorted(l1, key=lambda x:x.get('id'))
l2 = sorted(l2, key=lambda x:x.get('id'))
output = [d1 for d1,d2 in zip(l1, l2) if d2.get('grade') != 'Unavailable']

CodePudding user response:

I believe this is the Pythonic way to do it

Using List Comprehension:

l1 = [{"id": '1', "grade": 'A'}, {"id": '2', "grade": 'B'}, {"id": '3', "grade": 'A'}]
l2 = [{"id": '1', "grade": 'A'}, {"id": '2', "grade": 'B'}, {"id": '3', "grade": 'Unavailable'}]

#  Incase grade is always the same in l1 and l2 
#  Except it can have a value "Unavailable" in l2
l1 = [item for item in l2 if item['grade'] != 'Unavailable']

#  Otherwise if grade can be a different value in both lists for the same index
l1 = [l1[i] for i in range(len(l2)) if l2[i]["grade"] != 'Unavailable']

Output:

>>> [{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}] # l1_method_1
>>> [{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}] # l1_method_2

CodePudding user response:

The simplest way I can think of that doesn't make assumptions.

>>> [m for m in l1 if m['id'] not in (n['id'] for n in l2 if n['grade'] == 'Unavailable')]
[{'id': '1', 'grade': 'A'}, {'id': '2', 'grade': 'B'}]
  • Related