我正在用Python开发一个'TreeDict'类。这基本上是一个dict,允许您按排序顺序检索其键值对,就像Java中的Treemap集合类一样。
我已经基于关系数据库中的唯一索引的使用方式实现了一些功能,例如,函数,用于检索与一系列键,大于,小于或等于排序顺序的特定值的键,按排序顺序具有特定前缀的字符串或元组等对应的值。
不幸的是,我想不出任何需要像这样的课程的现实生活问题。我怀疑我们在Python中没有排序的原因是,在实践中它们并不经常被要求得到它,但我想被证明是错误的。
你能想到'TreeDict'的任何具体应用吗?这个数据结构最能解决的任何现实问题?我只是想知道这是否值得。
答案 0 :(得分:5)
我已经看到几个答案指向“按顺序排列”功能,这确实很重要,但没有突出显示另一个重要功能,即“找到带键的第一个条目> =这个”。即使没有真正需要从那里“走”,这也有很多用途。
例如(这出现在最近的SO回答中),假设您想要生成具有给定相对频率的伪随机值 - 也就是说,您给出了一个dict d
:
{'wolf': 42, 'sheep': 15, 'dog': 23, 'goat': 15, 'cat': 5}
并且需要一种方法来生成'狼',概率为百分之42(因为100是给定的相对频率的总和),'羊'中有15分,等等;并且不同值的数量可以非常大,相对频率也可以。
然后,将给定值(以任何顺序)存储为树图中的值,相应的键是直到该点的“总累积频率”。即:
def preprocess(d):
tot = 0
for v in d:
tot += d[v]
treemap.insert(key=tot, value=v)
return tot, treemap
现在,生成一个值可能非常快(O(log(len(d)))
),如下所示:
def generate(tot, treemap, r=random):
n = r.randrange(tot)
return treemap.firstGTkey(n).value
其中firstGTKey
是一个返回第一个条目(在此假设示例中具有.key
和.value
属性)的方法,其中包含键>给定的论点。我使用这种方法将大型文件存储为B树(例如使用bsddb.bt_open
和set_location
方法)。
答案 1 :(得分:2)
保持元素按排序顺序的原因是为了更快地检索。假设我希望字典中的所有值都在排序范围内。使用TreeDict然后使用常规hashmap,这要快得多。它基本上允许您按排序顺序保存字典中的所有内容。我知道在我正在使用的应用程序中使用这样的类来基本查询数据结构。
答案 2 :(得分:2)
当你需要按键的顺序浏览字典时,这很有用;偶尔会出现。我实际上发现它在某些编程竞赛中更为常见,然后是其他任何东西(想想ACM等)。
TreeMap最有用的功能是当你想快速找到最小或最大键时;使用排序字典这通常是单个方法调用;并且在算法上可以在O(log(n))时间内完成,而不是如果集合未排序则迭代每个键以寻找最小值/最大值。基本上,一个更友好的界面。
我遇到的一个比较常见的事情是,当特定名称标识对象时,您想要打印出根据名称排序的对象;说一个从目录名到目录中文件数的映射。
我使用过的另一个地方是excel电子表格包装器;从行号映射到行对象。这使您可以快速查找最后一行索引,而无需遍历每一行。
此外,当您可以根据HashMaps的需要轻松定义键上的比较关系,但不一定是散列函数时,它非常有用。我能想到的最好(尽管很弱)的例子是不区分大小写的字符串键。
答案 3 :(得分:1)
我在处理工业过程数据时经常使用Dict<DateTime, someClassOrValue>
-
阀门开/关,机械启动/停止等
当我需要在相当长的时间内比较开始/停止或开/关事件之间的时间间隔时,对键进行排序特别有用。
然而,由于我已经能够在C#中使用linq,我发现使用IEnumerables并使用IQueryable扩展方法来获取我需要的信息通常更容易。
答案 4 :(得分:1)
几乎所有“GROUP BY”报告都需要一个排序字典。
summary = sortedDefaultDict()
for row in somePileOfData:
summary[row.group_by] += row.balance
for k in sorted(summary.keys()):
print k, summary[k]
在数据仓库应用程序中经常这样做,很难表达它的核心。
如果sorted
函数调用不起作用,从长远来看会节省大量时间。
答案 5 :(得分:1)
答案 6 :(得分:0)
他们可以使各种算法更容易实现。