comparing two lists

Ladislav Andel ladaan at iptel.org
Fri Aug 24 09:23:08 CEST 2007


Peter Otten wrote:
> 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
>
>   
Thanks again for this solution, but I forgot to say that in the instance 
is a looping call which
need to be stopped before deleting any instance from items.
So I need to call stopLoop method in the given item in items before it 
gets removed.
If there is any addition to items it's quite easy to call
item.startLoop() method.


my class would look like (I use twisted but it should not make any 
difference):

class Item(object):
    def __init__(self, id, host, interval, **discarded):
        self._tuple = (id, host)
	self.interval = interval
    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
    def startLoop(self):
        self.l = task.LoopingCall(self.serverTest)
        self.l.start(self.interval, False)
    def serverTest(self):
        return getReply()       
         # this is just for example. It returns something on each start of the loop
         # but because it sends packets within network, it takes some time before it gets a reply
         # so if I remove this object instance before I get reply it gets broken somewhere else
         # and I need to stop the loop before removing. Hopefully, this make sence.
					
    def stopLoop(self):
        self.l.stop()










More information about the Python-list mailing list