【问题标题】:Ordered set of tuples with different hash and sort keys具有不同哈希和排序键的有序元组集
【发布时间】:2016-01-21 14:55:29
【问题描述】:

我有以下数据结构(带有示例数据):

edgeID (unique key) | timeStep (ordering key,            | value
                    |     can have multiple occurrences) | 
-----------------------------------------------------------------
"edge1"             | 15                                 | 12.1
"edge3"             | 18                                 | 17.32
"edge2"             | 23                                 | 15.1
"edge5"             | 23                                 | 65.6

我希望能够在这个结构上高效地执行以下任务:

  • 添加一个timeStep 高于任何其他已存储timeStep 的新数据条目。如果达到maxNumber的数据条目(例如20),则应删除具有最低timeStep的数据条目。
  • 合并两个数据集,保持maxNumber 的数据条目(例如 20 个)最高timeStep 条目)。

如何在python中实现这个数据结构?

我尝试了一种可行的方法:

  1. 一个存储数据的dict,一个SortedSet根据排序键存储键:

    data = {}
    dataOrder = SortedSet(key=lambda x: data[x][0])
    maxDataSize = 20
    
    def addData(edgeID, dataTuple):
        if(len(data) >= maxDataSize):
            # remove oldest value
            key = dataOrder.pop(0)
            del data[key]
        # add
        data[edgeID] = dataTuple
        dataOrder.add(edgeID)
    
    addData("edge1", (15, 12.1))
    

    这种方法的缺点是我将edgeID 存储了两次,而且我总是必须更新这两个数据结构。

我尝试了一种不起作用的方法:

  1. 只有一个SortedSet,它存储了整个数据并根据排序键进行排序:

    data = SortedSet(key=lambda x: x[1])
    maxDataSize = 20
    
    def addData(dataTuple):
        if(len(self.data) >= self.maxDataSize):
            # remove oldest value
            data.pop(0)
        # add
        data.add(dataTuple)
    
    addData(("edge1", 15, 12.1))
    

    这种方法不起作用的事实是,它让我输入相同的edgeID 两次,但使用不同的timeSteps,因为(我认为)它会散列整个元组而不仅仅是edgeID。不幸的是,我无法在 OrderedSet 构造函数中定义散列函数。这引出了我认为必须可行的第三种方法:

  2. 我可以定义一个实现 __hash__() 函数的类,而不是使用元组作为数据条目,它只会返回 edgeID。然后我可以将此类的对象存储在OrderedSet

这第三种方法真的是最好的吗?你有什么建议?

【问题讨论】:

    标签: python sorting data-structures hash set


    【解决方案1】:

    你想要的是一个heapq,按timeStep排序。

    抬头:https://docs.python.org/2/library/heapq.html

    本质上,python 的堆是一个最小堆,所以最小的时间步长会被存储在堆的顶部,并且可以在 O(1) 中获取。 每次,在将元素输入堆之前,检查它是否有 20 个或更多条目...如果有 >= 20 个条目,则从堆中 heappop...这将删除时间戳最少的条目...

    您可以将此与另一个 dict 协调,以便根据您喜欢的特定键更快地获取其他剩余条目

    【讨论】:

    • 感谢您的回答,但我缺少每个 edgeID 只允许一次的“设置”功能。或者我应该在插入之前检查每个密钥是否存在?然后我也可以使用 SortedList,但我猜使用堆的好处是对最低元素的 O(1) 访问。我的问题的重点是是否有一种数据结构可以帮助我避免这种“手动检查”。
    • 对 - 不幸的是,python 中没有指向对象的“引用”/“指针”的概念。所以你需要维护 2 个数据结构。 1) 用于在 o(1) 中获取最低时间戳的堆和 2) 用于检查实体存在的集合(再次为 o(1))...在插入堆检查集合之前以及从堆中弹出时,请确保从集合中移除...如果您为自己的数据结构创建一个简单的 api (get/set) 功能并将其公开给您的用户(其他程序),就足够简单了
    猜你喜欢
    • 2011-07-31
    • 2019-06-12
    • 1970-01-01
    • 2019-05-03
    • 2016-08-17
    • 2018-08-18
    • 2012-08-17
    • 2018-02-12
    • 2015-04-13
    相关资源
    最近更新 更多