有效地将不可用对象映射到列表中的索引

时间:2017-12-05 20:10:07

标签: python list dictionary hashable

Python列表

f = [x0, x1, x2]

可被视为从[0, 1, ..., len(f) - 1]到其元素集的映射的有效表示。 “有效”是指f[i]在O(1)时间内返回与i相关联的元素。

逆映射可以定义如下:

class Inverse:
    def __init__(self, f):
        self.f = f

    def __getitem__(self, x):
        return self.f.index(x)

这可行,但Inverse(f)[x] takes O(n) time on average

或者,可以使用dict

f_inv = {x: i for i, x in enumerate(f)}

这具有O(1)平均时间复杂度,但它要求列表中的对象为hashable

有没有办法定义一个逆映射,在O(1)平均时间内,使用不可用的对象提供基于等同的查找?

修改:示例输入和预期输出:

>>> f = [x0, x1, x2]
>>> f_inv = Inverse(f)  # this is to be defined
>>> f_inv[x0]  # in O(1) time
0
>>> f_inv[x2]  # in O(1) time
2

2 个答案:

答案 0 :(得分:1)

您可以创建一个关联字典,将对象ID映射回列表索引。

明显的缺点是你必须在索引中搜索身份对象,而不是在仅仅相等的eobject上搜索。

从好的方面来说,通过使用const path = require('path') module.exports = { entry : ['./app/index.js'], output : { // Get the path including the current directory node is running in path : path.resolve(__dirname, './build'), filename: 'bundle.js' } } 创建自定义MutableSequence类,您可以使用最少的代码编写一个类,将数据保存为序列和反向字典。

collections.abc

并且voilá:只需使用此对象代替列表,并使用public属性“reverse”来获取标识对象的索引。 感觉你可以通过尝试使用不同的策略来增加“MD”类的“智能”,比如使用对象本身,如果它们是可以清除的,并且只使用id或基于其他对象属性的其他自定义键,需要。这样,您可以减少搜索对同一对象的需求。

因此,对于列表上的普通操作,此类维护已恢复的字典同步。但是,不支持切片索引。 有关详细信息,请查看https://docs.python.org/3/library/collections.abc.html

上的文档

答案 1 :(得分:0)

不幸的是,你在这里遇到了算法限制。快速查找结构(如哈希表或二叉树)非常有效,因为它们将对象放在特定的桶中或根据它们的值对它们进行排序。这要求它们在您将它们存储在此结构中的整个时间内都是可散列的或一致,否则查找很可能会失败。

如果您需要的对象是可变的(通常是它们不可清除的原因),那么无论您跟踪的对象何时发生更改,您都需要更新数据结构。最安全的方法是创建不可变对象。如果需要更改对象,则创建一个新对象,从字典中删除旧对象,并将新对象作为具有相同值的键插入。

这里的操作对于字典的大小仍然是O(1),你只需要考虑在每次改变时复制对象的成本是否值得。