Python中是否有基数/帕特里夏/克里特位树?

12
我有大约10,000个单词作为反向索引集合,用于大约500,000个文档。两者都已标准化,因此索引是整数映射(单词ID)到整数集合(包含该单词的文档的ID)。

我的原型使用Python的set作为明显的数据类型。

当我搜索文档时,我找到N个搜索词及其对应的N个集合列表。我想返回这些N个集合的交集中的文档集合。

Python的“intersect”方法是通过成对的缩减来实现的。我认为,使用排序集合的并行搜索可以做得更好,只要库提供了一种快速获取i之后下一个条目的方法。

我一直在寻找这样的东西。多年前,我写了PyJudy,但我不再维护它,我知道需要多少工作才能让它再次达到我满意的阶段。我宁愿使用经过充分测试的其他人的代码,并且我希望支持快速序列化/反序列化的代码。

我找不到任何一个,或者至少没有Python绑定的任何一个。有avltree可以实现我想要的功能,但由于即使成对的集合合并也需要比我想要的时间长,我怀疑我想要在C/C++中完成所有操作。

您是否知道任何用作Python的C/C++扩展编写的基数/帕特里夏/克里特比特树库?

如果这样不行,我应该包装哪个最合适的库呢?Judy Array网站已经6年没有更新了,1.0.5版本是在2007年5月发布的。(虽然它可以干净地构建,所以也许它可以正常工作。)
(编辑:为了澄清我从API中想要什么,我需要像这样的东西:
def merge(document_sets):
    probe_i = 0
    probe_set = document_sets[probe_i]
    document_id = GET_FIRST(probe_set)

    while IS_VALID(document_id):
        # See if the document is present in all sets
        for i in range(1, len(document_sets)):
            # dynamically adapt to favor the least matching set
            target_i = (i + probe_i) % len(document_sets)
            target = document_sets[target_i]
            if document_id not in target_set:
                probe_i = target_id
                probe_set = document_sets[probe_i]
                document_id = GET_NEXT(probe_set, document_id)
                break
        else:
            yield document_id

我正在寻找一个能够实现GET_NEXT()函数的工具,以返回给定条目之后出现的下一个条目。这对应于Judy1N和其他Judy数组的类似条目。
该算法会动态适应数据,并优先选择命中率低的集合。对于我处理的数据类型,这可以使性能提高5-10%

以防万一:如果你还没有看过,可以去 http://www.nltk.org/ 看一下。 - 9000
我没有。快速扫描没有找到任何相关的内容。你能更具体一些吗? - Andrew Dalke
你真的需要一个生成器吗?还是你最终只是想获得一组文档编号的集合/列表? - Justin Peel
@Justin:我所需要的只是最终的集合。这个例子展示了我如何利用有序集合来实现更快的交集函数。如果没有迭代器,那么有些罕见的情况可能会返回一个包含1,500万项的集合交集,但这并不是我的问题的严重关注点。 - Andrew Dalke
集合确实是这里的最佳选择。问题在于多重集合交集的实现方式,会导致创建(N-1)个集合,这就是巨大减速的根源。我个人会自己制作基于集合的(C)版本,以替代Python发行版中的版本。我认为这也应该成为Python发行版中的一个请求更改。你使用的是哪个版本的Python? - Justin Peel
@Justin:我计划提出/实现这个想法,还有一个新功能。还应该有一个(has, has_not) = set.split(iterable),其中“has”具有在iterable中的所有“set”元素,而其他“set”元素进入“has_not”。我正在使用2.6,并查看了2.7源代码以查看其实现。 - Andrew Dalke
2个回答

5

是的,有一些,但我不确定它们是否适用于您的用例:但似乎没有一个是您所要求的。

BioPython在C中有一个Trie实现。

啊,这里有一个很好的讨论,包括基准测试:http://bugs.python.org/issue9520

其他(一些非常陈旧)实现:

http://pypi.python.org/pypi/radix

py-radix是存储和检索IPv4和IPv6网络前缀的radix树数据结构的实现。

https://bitbucket.org/markon/patricia-tree/src

patricia-tree的Python实现

http://pypi.python.org/pypi/trie

前缀树(Trie)实现。

http://pypi.python.org/pypi/logilab-common/0.50.3

patricia.py:PATRICIA trie的Python实现(用于检索编码为字母数字的信息的实用算法)。


Biopython的trie在API中不支持“获取i之后的下一个条目”。Radix专门用于IPv4/6格式的地址,而不是通用库。Trie是(正如您所说)纯Python,并且它没有“获取下一个”接口。“patricia.py”在logilab存储库中明显缺失。 - Andrew Dalke

3

最近我在 datrie 中添加了迭代器支持,你可以尝试一下。


很遗憾,对我来说崩溃了,使用的是Python 3.3,Win7 32位系统,datrie 0.4.2版本,我尝试运行在Github页面上提供的示例代码。 :-/ - laurasia
加载datrie时应用程序崩溃:c0000374,看起来像是堆损坏。 - laurasia
请在错误跟踪器中提交一个问题,好吗?字母表设置正确吗? - Mikhail Korobov
据我所记,我将“abcdef”设置为字母表,并仅添加了t['a'] = 'a',t['b'] = 'b'等,其中t是一个Trie。我会尽快详细说明这一点,我现在已经删除了datrie,并将在今晚再次安装它。我使用mingw 4.6.2 win32进行编译。 - laurasia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接