Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match set of dictionaries. Most elegant solution. Python

Given two lists of dictionaries, new one and old one. Dictionaries represent the same objects in both lists.
I need to find differences and produce new list of dictionaries where will be objects from new dictionaries only and updated attributes from old dictionaries.
Example:

   list_new=[
             { 'id':1,
               'name':'bob',
               'desc': 'cool guy'
              },
             
             { 'id':2,
               'name':'Bill',
               'desc': 'bad guy'
              },

              { 'id':3,
               'name':'Vasya',
               'desc': None
              },
        ]

    list_old=[
             { 'id':1,
               'name':'boby',
               'desc': 'cool guy',
                'some_data' : '12345'
              },
             { 'id':2,
               'name':'Bill',
               'desc': 'cool guy',
               'some_data' : '12345'

              },
              { 'id':3,
               'name':'vasya',
               'desc': 'the man',
               'some_data' : '12345'
              },
              { 'id':4,
               'name':'Elvis',
               'desc': 'singer',
               'some_data' : '12345'
              },
            ]
            

In that example I want produce new list where will be only new guys from list_new with updated data. Matched by id. So Bob will become Boby, Bill will become coll guy, Vasya become - the man. End Elvis have to be absent.

Give me an elegant solution. With less amount of iteration loops.

There is way, I resolve that. Which is not the best:

 def match_dict(new_list, old_list)
    ids_new=[]
    for item in new_list:
            ids_new.append(item['id'])
    result=[] 
    for item_old in old_medias:
        if item_old['id'] in ids_new:
            for item_new in new_list:
                if item_new['id']=item_old['id']
                    item_new['some_data']=item_old['some_data']
                    result.append(item_new)
    return result

The reason why I'm doubt, because there is loop inside loop. If there will be lists of 2000 items the process would take same time.

like image 242
Pol Avatar asked Mar 09 '11 21:03

Pol


1 Answers

Can't quite get it to one line, but here's a simpler version:

def match_new(new_list, old_list) :
    ids = dict((item['id'], item) for item in new_list)
    return [ids[item['id']] for item in old_list if item['id'] in ids]
like image 175
koblas Avatar answered Oct 07 '22 00:10

koblas