How to delete from list of dictionary if key matches after value check

Viewed 61

Below is my dictionary

myd = [
  {
    'name': 'Abc',
    'id': '101',
    'status': 'Success',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  },
  
  {
    'name': 'Abc',
    'id': '101',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-21 12:25:32:013302'  },
    
    {
    'name': 'def',
    'id': '102',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  },
    
    {
    'name': 'ghi',
    'id': '103',
    'status': 'Success',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  },
 {
    'name': 'ijk',
    'id': '110',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  },
 {
    'name': 'ijk',
    'id': '110',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  }
]
  • I need to extract dictionary status is 'Failed' only
  • If status is 'Success' for id which status is 'Failed' then that dictionaries has to delete from list
  • Only Failed has to do add in the dictionary
  • If both id's are failed then it can add that dictionary

Expected out

myd = [
        {
    'name': 'def',
    'id': '102',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  },
{
    'name': 'ijk',
    'id': '110',
    'status': 'Failed',
    'lastModifiedDate': '2022-02-14 12:25:32:013302'  }
]

code is below

#Remove duplicates
new = [dict(t) for t in {tuple(d.items()) for d in myd}]
for i in new:
  if i['id] == 
4 Answers

You can find all the ones that succeeded and filter based off that. Using a dictionary with id for the keys and the dict as the values, and just get the values to make the result unique:

succeeded = {d["id"] for d in myd if d["status"] == "Success"}
result = list({d["id"]: d for d in myd if d["id"] not in succeeded}.values())

Result (pretty printed):

[
  {'id': '102',
    'lastModifiedDate': '2022-02-14 12:25:32:013302',
    'name': 'def',
    'status': 'Failed'
  },
  {'id': '110',
    'lastModifiedDate': '2022-02-14 12:25:32:013302',
    'name': 'ijk',
    'status': 'Failed'
  }
]

Keep in mind this ignores the lastModifiedDate but if you want to take that into account it's pretty straight forward.

Use sets to check membership for speed. Use set comprehension to first create the list of successful ids. Iterate over you list myd and check you conditions; if they are satisfied, then append to the resulting list of ids, and add the id to the set of seen ids.

successful_ids = {x['id'] for x in myd if x['status'] == 'Success'}
seen_ids = set()

new_d = []
for x in myd:
    if (x['status'] == 'Failed'
        and x['id'] not in successful_ids
        and x['id'] not in seen_ids):
        new_d.append(x)
        seen_ids.add(x['id'])

print(new_d)
# [{'name': 'def', 'id': '102', 'status': 'Failed', 'lastModifiedDate': '2022-02-14 12:25:32:013302'}, {'name': 'ijk', 'id': '110', 'status': 'Failed', 'lastModifiedDate': '2022-02-14 12:25:32:013302'}]

The simplest though not fastest solution is to build a comprehension of failed ids, and use it to pick one dictionary per failing id

failed_ids = list(set([d['id'] for d in myd if d['status'] == 'Failed']))
result = []
for d in myd:
    if d['id'] in failed_ids:
        failed_ids.delete(d['id'])
        result.append(d) 

or, without comprehension

result = []
failed_ids = []
for d in myd:
    if d['id'] not in failed_ids and d['status'] == "Failed":
        failed_ids.append(d['id'])
        result.append(d)
myd = result 
print('results')
print(myd)

Using sets for checking already included id will increase performance but would not be noticeable on small lists

Just realized you do not want anything with one or more success records, if so build success list ahead and collect already included into failed id list

succ_ids = list(set([d['id'] for d in myd if d['status'] != 'Failed']))
fail_ids = []
result = [] 
for d in myd:     
    if d['status'] not in succ_ids and d['status'] not in fail_ids:
         result.append(d) 
         fail_ids.append(d['id']) 
counter = 0
newDict=[]

for i in myd:# this for is getting Failed ones into the newDict
    if i['status'] == 'Failed':
        newDict.append(myd[counter])
    counter +=1

counter = 0
for i in newDict:#this for is destroying duplicates
    if i['id'] in newDict[counter]['id']:
        newDict.pop(counter)
    counter +=1
print(newDict)
Related