comparing two lists

Peter Otten __peter__ at web.de
Thu Aug 23 23:53:53 CEST 2007


Ladislav Andel wrote:

> Peter Otten wrote:
>> Ladislav Andel wrote:
>>
>>   
>>> what would be the most efficient way to do following?
>>>
>>> I have a list of dictionaries  taken from DB e.g.
>>> dblist = [{'id:1, 'host':'google.com','ip_address':'1.2.3.4'},
>>> {'id:3, 'host':'yahoo.com','ip_address':'5.6.7.8'},
>>> {'id:9, 'host':'msn.com','ip_address':'11.3.2.3'}]
>>>
>>> and list of object instances in memory(it's just for example)
>>> which are looping within itself and testing particular hosts
>>>
>>> memlist = [<instance 1>,<instance 2>]
>>> memlist[0].id  is 1 and  memlist[0].host is google.com etc.
>>> memlist[1].id  is 9 and  memlist[1].host is msn.com etc.
>>>
>>> Now I want to add a new instance to memlist since id=3(in dblist) is not
>>> in memlist.
>>> How would you iterate through it and insert a new instance?
>>>
>>> The result should be:
>>> memlist = [<instance 1>,<instance 2>, <instance 3>]
>>> memlist[0].id  is 1 and  memlist[0].host is google.com etc.
>>> memlist[1].id  is 3 and  memlist[1].host is yahoo.com etc.
>>> memlist[2].id  is 9 and  memlist[2].host is msn.com etc.
>>>     
>>
>> You should replace the memlist with a dictionary using (host, id) tuples
>> as the keys. Here's an example that uses a set but requires you to modify
>> the <instance N> class:
>>
>> dblist = [{'id':1, 'host':'google.com','ip_address':'1.2.3.4'},
>> {'id':3, 'host':'yahoo.com','ip_address':'5.6.7.8'},
>> {'id':9, 'host':'msn.com','ip_address':'11.3.2.3'}]
>>
>> class Item(object):
>>     def __init__(self, id, host, **discarded):
>>         self._tuple = (id, host)
>>     def __hash__(self):
>>         return hash(self._tuple)
>>     def __eq__(self, other):
>>         return self._tuple == other._tuple
>>     def __repr__(self):
>>         return "Item(id=%r, host=%r)" % self._tuple
>>
>> items = set([Item(1, "google.com")])
>> for d in dblist:
>>     item = Item(**d)
>>     if item not in items:
>>         print "adding", item
>>         items.add(item)
>>     else:
>>         print item, "already there"
>>
>>   
> Thank you for this nice solution. I wouldn't be able to write it this
> way at all

Then think twice before you use it. The dictionary approach should be
straightforward.

> but what about removing from memlist if there is less items in dblist
> than in items (instances)?
> I will have to iterate over items(instances) and remove that one which
> is not in dblist I guess.

Yes, but again, if you use a dictionary instead of a list the lookup will be
efficient.

To follow up on my previous post: with sets there is a concise spelling:

items &= set(Item(**d) for d in dblist)

or even

items.intersection_update(Item(**d) for d in dblist)

if you don't mind object identity.

Peter




More information about the Python-list mailing list