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() -- http://mail.python.org/mailman/listinfo/python-list