超级快速、高效存储的 Python Trie。
项目描述
datrie

超级快速、高效存储的 Python Trie (2.x 和 3.x)。使用 libdatrie。
安装
pip install datrie
用法
创建一个能够存储具有小写 ascii 键的项的新 trie
>>> import string >>> import datrie >>> trie = datrie.Trie(string.ascii_lowercase)
trie 变量是一个类似于字典的对象,它可以具有特定范围内的 Unicode 键和 Python 对象作为值。
除了实现映射接口之外,tries还简化了查找给定前缀的项,反之亦然,查找键为给定字符串前缀的项。作为常见的特殊情况,也支持查找最长的前缀项。
向其中添加一些值(datrie的键必须是unicode;以下示例针对Python 2.x)
>>> trie[u'foo'] = 5 >>> trie[u'foobar'] = 10 >>> trie[u'bar'] = 'bar value' >>> trie.setdefault(u'foobar', 15) 10
检查u'foo'是否在trie中
>>> u'foo' in trie True
获取一个值
>>> trie[u'foo'] 5
查找一个单词的所有前缀
>>> trie.prefixes(u'foobarbaz') [u'foo', u'foobar'] >>> trie.prefix_items(u'foobarbaz') [(u'foo', 5), (u'foobar', 10)] >>> trie.iter_prefixes(u'foobarbaz') <generator object ...> >>> trie.iter_prefix_items(u'foobarbaz') <generator object ...>
查找一个单词的最长前缀
>>> trie.longest_prefix(u'foo') u'foo' >>> trie.longest_prefix(u'foobarbaz') u'foobar' >>> trie.longest_prefix(u'gaz') KeyError: u'gaz' >>> trie.longest_prefix(u'gaz', default=u'vasia') u'vasia' >>> trie.longest_prefix_item(u'foobarbaz') (u'foobar', 10)
检查trie是否有具有给定前缀的键
>>> trie.has_keys_with_prefix(u'fo') True >>> trie.has_keys_with_prefix(u'FO') False
从trie中获取具有给定前缀的所有项
>>> trie.keys(u'fo') [u'foo', u'foobar'] >>> trie.items(u'ba') [(u'bar', 'bar value')] >>> trie.values(u'foob') [10]
从trie中获取以给定前缀开始的特定单词的所有后缀
>>> trie.suffixes() [u'pro', u'producer', u'producers', u'product', u'production', u'productivity', u'prof'] >>> trie.suffixes(u'prod') [u'ucer', u'ucers', u'uct', u'uction', u'uctivity']
保存和加载一个trie(值必须是可序列化的)
>>> trie.save('my.trie') >>> trie2 = datrie.Trie.load('my.trie')
Trie和BaseTrie
在datrie包中有两个Trie类: datrie.Trie 和 datrie.BaseTrie。 datrie.BaseTrie略快,内存使用也更少,但它只能存储整数,范围是-2147483648 <= x <= 2147483647。 datrie.Trie稍慢,但可以存储任何Python对象作为值。
如果您不需要值或整数值是可以接受的,则使用datrie.BaseTrie
import datrie import string trie = datrie.BaseTrie(string.ascii_lowercase)
自定义迭代
如果内置的trie方法不适合您,则可以使用 datrie.State 和 datrie.Iterator 来实现自定义遍历。
例如,让我们为我们的trie查找所有以'fo'结尾的后缀并获取值
>>> state = datrie.State(trie) >>> state.walk(u'foo') >>> it = datrie.Iterator(state) >>> while it.next(): ... print(it.key()) ... print(it.data)) o 5 obar 10
性能
性能是在与Python字典比较的情况下测量的,其中字典有100k个唯一的unicode单词(英语和俄语)作为键,'1'作为值。
datrie.Trie大约使用5M内存来存储100k个单词;根据我的非科学的测试,Python字典大约使用22M。
这个trie实现比python的dict在__getitem__上的速度慢2-6倍;基准测试结果(macbook air i5 1.8GHz,“1.000M ops/sec” == “1 000 000 operations per second”)
Python 2.6: dict __getitem__: 7.107M ops/sec trie __getitem__: 2.478M ops/sec Python 2.7: dict __getitem__: 6.550M ops/sec trie __getitem__: 2.474M ops/sec Python 3.2: dict __getitem__: 8.185M ops/sec trie __getitem__: 2.684M ops/sec Python 3.3: dict __getitem__: 7.050M ops/sec trie __getitem__: 2.755M ops/sec
查找给定单词的前缀几乎和__getitem__一样快(结果针对Python 3.3)
trie.iter_prefix_items (hits): 0.461M ops/sec trie.prefix_items (hits): 0.743M ops/sec trie.prefix_items loop (hits): 0.629M ops/sec trie.iter_prefixes (hits): 0.759M ops/sec trie.iter_prefixes (misses): 1.538M ops/sec trie.iter_prefixes (mixed): 1.359M ops/sec trie.has_keys_with_prefix (hits): 1.896M ops/sec trie.has_keys_with_prefix (misses): 2.590M ops/sec trie.longest_prefix (hits): 1.710M ops/sec trie.longest_prefix (misses): 1.506M ops/sec trie.longest_prefix (mixed): 1.520M ops/sec trie.longest_prefix_item (hits): 1.276M ops/sec trie.longest_prefix_item (misses): 1.292M ops/sec trie.longest_prefix_item (mixed): 1.379M ops/sec
查找以给定前缀开始的单词主要受总结果计数限制(这可以在未来得到改善,因为大量的时间被花在将utf_32_le字符串解码为Python的unicode上)
trie.items(prefix="xxx"), avg_len(res)==415: 0.609K ops/sec trie.keys(prefix="xxx"), avg_len(res)==415: 0.642K ops/sec trie.values(prefix="xxx"), avg_len(res)==415: 4.974K ops/sec trie.items(prefix="xxxxx"), avg_len(res)==17: 14.781K ops/sec trie.keys(prefix="xxxxx"), avg_len(res)==17: 15.766K ops/sec trie.values(prefix="xxxxx"), avg_len(res)==17: 96.456K ops/sec trie.items(prefix="xxxxxxxx"), avg_len(res)==3: 75.165K ops/sec trie.keys(prefix="xxxxxxxx"), avg_len(res)==3: 77.225K ops/sec trie.values(prefix="xxxxxxxx"), avg_len(res)==3: 320.755K ops/sec trie.items(prefix="xxxxx..xx"), avg_len(res)==1.4: 173.591K ops/sec trie.keys(prefix="xxxxx..xx"), avg_len(res)==1.4: 180.678K ops/sec trie.values(prefix="xxxxx..xx"), avg_len(res)==1.4: 503.392K ops/sec trie.items(prefix="xxx"), NON_EXISTING: 2023.647K ops/sec trie.keys(prefix="xxx"), NON_EXISTING: 1976.928K ops/sec trie.values(prefix="xxx"), NON_EXISTING: 2060.372K ops/sec
与dict相比,随机插入时间非常慢,这是双数组tries的限制;更新相当快。如果您想构建一个trie,请考虑在插入之前对键进行排序
dict __setitem__ (updates): 6.497M ops/sec trie __setitem__ (updates): 2.633M ops/sec dict __setitem__ (inserts, random): 5.808M ops/sec trie __setitem__ (inserts, random): 0.053M ops/sec dict __setitem__ (inserts, sorted): 5.749M ops/sec trie __setitem__ (inserts, sorted): 0.624M ops/sec dict setdefault (updates): 3.455M ops/sec trie setdefault (updates): 1.910M ops/sec dict setdefault (inserts): 3.466M ops/sec trie setdefault (inserts): 0.053M ops/sec
其他结果(注意,len(trie)当前是通过trie遍历实现的)
dict __contains__ (hits): 6.801M ops/sec trie __contains__ (hits): 2.816M ops/sec dict __contains__ (misses): 5.470M ops/sec trie __contains__ (misses): 4.224M ops/sec dict __len__: 334336.269 ops/sec trie __len__: 22.900 ops/sec dict values(): 406.507 ops/sec trie values(): 20.864 ops/sec dict keys(): 189.298 ops/sec trie keys(): 2.773 ops/sec dict items(): 48.734 ops/sec trie items(): 2.611 ops/sec
请将这些基准测试结果视为仅供参考;这是一个非常简单的基准测试,可能无法覆盖您的用例。
当前限制
键必须是unicode(Python 2.x下,字节字符串没有隐式转换,抱歉);
没有键/值/项的迭代器版本(这尚未实现);
在pypy下,它非常慢,可能还有bug;
库未针对窄Python构建进行测试。
贡献
开发发生在github上:https://github.com/pytries/datrie。
请随时提交想法、错误报告和pull请求。
运行测试和基准测试
请确保tox已安装并运行
$ tox
从源代码签出。测试应在Python 2.7和3.4+下通过。
$ tox -c tox-bench.ini
运行基准测试。
如果您已经更改了源代码,请确保已安装cython并运行
$ update_c.sh
每次在执行tox命令之前。
请注意,基准测试数据不包括在发布版本的tar.gz中,因为基准数据很大,这可以节省大量带宽;请使用来自github或bitbucket的源代码签出来进行基准测试。
许可
根据LGPL v2.1授权。CHANGES =======
0.8.2 (2020-03-25)
通过将cython作为构建时间依赖项并从仓库(和sdist)中删除cython生成的c文件来提供向后兼容的Python支持。
修复collections.abc.MutableMapping导入
CI和测试更新
调整库名为不破坏某些链接器
0.8.1(跳过)
本版本有意跳过
0.8 (2019-07-03)
Python 3.7兼容性;扩展程序使用Cython 0.29.11重新构建。
Trie.get函数;
删除对Python 2.6和3.3的支持;
删除不再需要的libdatrie补丁;
测试和CI修复。
0.7.1 (2016-03-12)
将捆绑的C库更新到版本0.2.9;
使用trie_enumerate实现了Trie.__len__;
使用Cython 0.23.4重新构建Cython包装器;
将Trie更改为实现collections.abc.MutableMapping;
修复了在Python2.X上导致段错误的Trie序列化;
0.7 (2014-02-18)
捆绑的libdatrie C库更新到版本0.2.8;
新增了.suffixes()方法(感谢Ahmed T. Youssef);
使用Cython 0.20.1重新构建包装器。
0.6.1 (2013-09-21)
修复了Visual Studio的构建(感谢Gabi Davar)。
0.6 (2013-07-09)
使用Cython 0.19.1重新构建datrie;
iter_prefix_values、prefix_values和longest_prefix_value方法用于datrie.BaseTrie和datrie.Trie(感谢Jared Suttles)。
0.5.1 (2013-01-30)
最近在longest_prefix和longest_prefix_item中引入的内存泄漏已修复。
0.5 (2013-01-29)
longest_prefix和longest_prefix_item方法已修复;
使用Cython 0.18重新构建datrie;
修复了README中的误导性基准测试结果;
将State._walk重命名为State.walk_char。
0.4.2 (2012-09-02)
更新到最新的libdatrie;这使得.keys()方法稍微慢一些,但消除了keys长度的限制。
0.4.1 (2012-07-29)
如果可用,则使用cPickle保存/加载datrie.Trie。
0.4 (2012-07-27)
libdatrie改进和错误修复,包括C迭代器API支持;
使用datrie.State和datrie.Iterator提供自定义迭代支持。
速度改进:__length__、keys、values和items方法应该快2倍。
本版本不支持长度超过32768的keys。
0.3 (2012-07-21)
本版本没有添加新功能或速度改进。
datrie.new已弃用;使用具有相同参数的datrie.Trie;
小型测试和基准测试改进。
0.2 (2012-07-16)
datrie.Trie项可以有任何Python对象作为值(0.1.x版本的Trie变为datrie.BaseTrie);
longest_prefix和longest_prefix_items已修复;
保存 和 加载 已重写;
setdefault 方法。
0.1.1 (2012-07-13)
支持 Windows(上游 libdatrie 的更改已合并);
许可证从 LGPL v3 更改为 LGPL v2.1,以匹配 libdatrie 许可证。
0.1 (2012-07-12)
初始发布。
项目详情
下载文件
下载适合您平台的自定义文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源代码分发
构建分发
datrie-0.8.2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 525b08f638d5cf6115df6ccd818e5a01298cd230b2dac91c8ff2e6499d18765d |
|
MD5 | 0478ffb9b9a28e6192cc84d94c65a8fc |
|
BLAKE2b-256 | 9dfedb74bd405d515f06657f11ad529878fd389576dca4812bea6f98d9b31574 |
datrie-0.8.2-pp373-pypy36_pp73-win32.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 89ff3d41df4f899387aa07b4b066f5da36e3a10b67b8aeae631c950502ff4503 |
|
MD5 | b333cb5b1964e5b17be0ddc3315f3099 |
|
BLAKE2b-256 | c4aa94c42a2dd30c4923bffe3ab59e4416c3f7e72dbd32a89bcdd8d43ff1d5d7 |
datrie-0.8.2-pp273-pypy_73-win32.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | b07bd5fdfc3399a6dab86d6e35c72b1dbd598e80c97509c7c7518ab8774d3fda |
|
MD5 | 99bf7ef877a592cb7299e8acb7545105 |
|
BLAKE2b-256 | 440253f0cf0bf0cd629ba6c2cc13f2f9db24323459e9c19463783d890a540a96 |
datrie-0.8.2-cp38-cp38-win_amd64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f61cf2726f04c08828bfb4e7af698b0b16bdf2777c3993d042f2898b8e118f21 |
|
MD5 | 29ecfd141a2862dc7616a7ab85598caf |
|
BLAKE2b-256 | 2d69909fb50e7b572dc0b5a43e499d8acbba2e314b578a8480cd92ca9425f9f8 |
datrie-0.8.2-cp38-cp38-win32.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 67603594f5db5c0029b1cf86a08e89cde015fe64cf0c4ae4e539c61114396729 |
|
MD5 | afe9cc7423c26ec4a75914fea58beadf |
|
BLAKE2b-256 | 90de580e485bca7a8f30ebd89c0a2efdbbae4f596f8dea5013713b9a3513e08f |
datrie-0.8.2-cp38-cp38-manylinux1_x86_64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | b2d80fa687173cb8f8bae224ef00d1ad6bda8f8597bbb1a63f85182c7d91aeb3 |
|
MD5 | 51386144f9c0ff3bb902e2c793960931 |
|
BLAKE2b-256 | 3f431ff434249b082c233afcb0217884a2cd542e4696900aace249e36b26df88 |
哈希值 为 datrie-0.8.2-cp38-cp38-macosx_10_9_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e0582435a4adef1a2fce53aeedb656bf769b0f113b524f98be51d3e3d40720cb |
|
MD5 | 7f92dcbaf76231df5b7b16aeb7392573 |
|
BLAKE2b-256 | 2b60d5d83f080f2bf84902e7ede9b3776778433f6775c46eb296f78cf88ca197 |
哈希值 为 datrie-0.8.2-cp37-cp37m-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e1d704ee4fdc03f02d7dacc4d92052dbd490dba551509fccfd8ee52c9039d4ad |
|
MD5 | 74fc618e8aa368d38a1522540b942d46 |
|
BLAKE2b-256 | 90f8c6daa335b0b5f3a6932e8b62b6f848e87c7f855ab6e94376051c9e228553 |
哈希值 为 datrie-0.8.2-cp37-cp37m-macosx_10_9_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | dbe04704eb41b8440ca61416d3670ca6ddeea847d19731cf121889bac2962d07 |
|
MD5 | 3c6d37dbc92eadd8d6c1ec3025b66888 |
|
BLAKE2b-256 | 223214e19f05007ecc0c3872aa2ffc9a160c4d89fd42310f3864c0399bd8bf20 |
哈希值 为 datrie-0.8.2-cp36-cp36m-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 327d9c17efaebc66d1956dca047b76fdd0e5b989d63cb55b9038ec09d8769089 |
|
MD5 | a9d50d12bdae471ca8cf833fdfb20004 |
|
BLAKE2b-256 | 0be76c36d488e23f4b421b1351117417524ae2d3e138fdab83d23630c948199b |
哈希值 为 datrie-0.8.2-cp36-cp36m-macosx_10_9_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | b6fd6c7c149b410a87d46072c1c98f6e87ec557802e1d0e09db7b858746e8550 |
|
MD5 | 7d6ee138262b8450be0cf21c3eba08ec |
|
BLAKE2b-256 | 9a9820763bc7b17f4a34c1d47a14cec0f9e6fee88994c21893a4e3e169ab3676 |
哈希值 为 datrie-0.8.2-cp35-cp35m-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0e3b76676abbae2368cce6bf605bb0ba7cfd11f2c420b96d67959f353d5d423f |
|
MD5 | f493ea119d88e16e942f1e21745ef4a2 |
|
BLAKE2b-256 | 10632ff02b530802832b0cbe0535c6b4e0024f2997286b2cbd18670eb5034907 |
哈希值 为 datrie-0.8.2-cp35-cp35m-macosx_10_6_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 651c63325056347b86c5de7ffeea8529230a5787c61ee6dcabc5b6c644bd3252 |
|
MD5 | aa3d82f58d0a3e91e3205432372b8c1f |
|
BLAKE2b-256 | 87bec2c2ece6536da2886e67de40c04f4369c50de107ec3541aeb29b91a75840 |
哈希值 用于 datrie-0.8.2-cp34-cp34m-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2de594d84a2f43a09ddc15316a8afd48aae0fdc456f9279d0940aa59c473d9d5 |
|
MD5 | d34ed3c8a3f340a0f6d05703715bd39d |
|
BLAKE2b-256 | fce90db8800a4c8dc197fc55a11102fe3a02e064d8966b1cadcabbaa51861344 |
哈希值 用于 datrie-0.8.2-cp27-cp27mu-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | bf5c956c0a9a9d0f07e3c8923746279171096de18a8a51685e22d9817f8755a6 |
|
MD5 | d97b50a58826f328dd773d2949d25486 |
|
BLAKE2b-256 | 88423abe71838ad52622ca3601265969fa76c1653d2fa82486cfa710f1478b53 |
哈希值 用于 datrie-0.8.2-cp27-cp27m-manylinux1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6c9b333035312b79e6e9a10356d033e3d29aadbae6365007f706c854b3a94674 |
|
MD5 | 7b7312c62d7fd7f9a6cf3ce7de6e6755 |
|
BLAKE2b-256 | 4583062eb20c581f6e90b0fc52b2093f72f4d9d47efbc4010bab82957e00e840 |
哈希值 用于 datrie-0.8.2-cp27-cp27m-macosx_10_7_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 53969643e2794c37f024d5edaa42d5e6e2627d9937ddcc18d99128e9df700e4c |
|
MD5 | 3704eb7b5ba0244039abe8ba9d2a2413 |
|
BLAKE2b-256 | 59483ae10482706efd3acb732a2d60e03c613a38e2d41eddf0b84ec40a6ae753 |