Set class with timed auto remove of elements

前端 未结 2 1295
故里飘歌
故里飘歌 2021-01-14 09:15

I\'m writing a software with Python and I need a class to store a set of elements (order is not relevant and not repeated elements), like the Python class set,

相关标签:
2条回答
  • 2021-01-14 09:51

    I don't see any reason not to go with multithreading. As it is really easy to implement, with minimum code. Roughly something like this:

    import threading
    import time
    
    def ttl_set_remove(my_set, item, ttl):
        time.sleep(ttl)
        my_set.remove(item)
    
    class MySet(set):
        def add(self, item, ttl):
            set.add(self, item)
            t = threading.Thread(target=ttl_set_remove, args=(self, item, ttl))
            t.start()
    

    test:

    s = MySet()
    s.add('a', 20)
    s.add('b', 10)
    s.add('c', 2)
    
    print(s)
    time.sleep(5)
    print(s)
    
    >>> 
    MySet({'c', 'b', 'a'})
    MySet({'b', 'a'})
    
    0 讨论(0)
  • 2021-01-14 10:03

    Just an idea (of course, it isn't the best one): Use a dictionary to store the timestamp of each addition plus the concrete timeout for each item. Then, when you want to check if an item is in the set, you have to compare the current time with the value in the dictionary. This way you don't need to start a new thread to remove each item when the timeout is finished (just keep the key in the dictionary, and update it if the item is added again).

    With this solution you have to implement __contains__ and __iter__ apart from add, to make sure 'a' in myset and iter(myset) returns consistent results.

    import time
    
    class TimedSet(set):
        def __init__(self):
            self.__table = {}
        def add(self, item, timeout=1):
            self.__table[item] = time.time() + timeout
            set.add(self, item)
        def __contains__(self, item):
            return time.time() < self.__table.get(item)
        def __iter__(self):
            for item in set.__iter__(self):
                if time.time() < self.__table.get(item):
                    yield item
    

    And a possible example of usage:

    t_set = TimedSet()
    t_set.add('a')
    time.sleep(0.6)
    print 'a' in t_set
    time.sleep(0.6)
    print 'a' in t_set
    
    t_set.add('x', 0.3)
    t_set.add('y', 0.4)
    t_set.add('z', 0.5)
    time.sleep(0.35)
    for item in t_set:
        print item
    
    0 讨论(0)
提交回复
热议问题