views:

73

answers:

2

I have a list of dictionaries that I get back from a web service call.

listA = [{'name':'foo', 'val':'x'}, 
         {'name':'bar', 'val':'1'},
         {'name':'alice','val':'2'}]

I need to compare results from the previous call to the service and pull out changes. so on next call I may get:

listB = [{'name':'foo', 'val':'y'},
         {'name':'bar', 'val':'1'},
         {'name':'eve','val':'z'}]

The ordering is not guaranteed and nor is the length of list. names won't change. The actual data has several more keys but I'm only concerned with 'val'.

Trying to find a way to get back a list of the names that have had their values change between calls only for the names that are in both lists.

changed = ['foo'] # or [{'name':'foo'}]

Thanks.

+4  A: 

I'd build an auxiliary dict to store listA's information more sensibly:

auxdict = dict((d['name'], d['val']) for d in listA)

then the task becomes very easy:

changed = [d['name'] for d in listB 
           if d['name'] in auxdict and d['val'] != auxdict[d['name']]]
Alex Martelli
A: 

First off, please turn that braindead format from your library into a real dict:

>>> listA = [{'name':'foo', 'val':'x'},{'name':'bar', 'val':'1'},{'name':'alice','val':'2'}]
>>> listB = [{'name':'foo', 'val':'y'},{'name':'bar', 'val':'1'},{'name':'eve','val':'z'}]
>>> def dicter(l):
...     return dict([(i['name'],i['val']) for i in l])
...
>>> listA=dicter(listA)
>>> listA
{'foo': 'x', 'bar': '1', 'alice': '2'}
>>> listB=dicter(listB)
>>> listB
{'foo': 'y', 'bar': '1', 'eve': 'z'}

Then, this becomes relatively easy:

>>> answer = [k for k,v in listB.items() if k in listA and listA[k] != v]
>>> answer
['foo']
>>>
Jorenko
You might consider skipping the intermediate list by using a generator in your `dicter` function: `dict([(i['name'],i['val']) for i in l])` becomes `dict( (i['name'],i['val']) for i in l)`
Seth Johnson