嗯......我有一个简单的请求,即建立一个条目,即时过滤条目列表。 (想想一个编辑器自动完成功能)
请求是支持整个列表中的正则表达式过滤器,并仅显示匹配的条目。
如,
该列表包含:
abc.efg.hij.entry
abc.ddd.hij.entry2
hij.some.value.entry
输入条目
Value : List
hij : abc.efg.hij.entry, abc.ddd.hij.entry2, hij.some.value.entry
ddd : abc.ddd.hij.entry2
dd*entry : abc.ddd.hij.entry2
val : hij.some.value.entry
以下是我用于过滤列表的代码:
regex = re.compile(r"{0}".format(entry_value), re.IGNORECASE)
display_list = list(filter(regex.search, display_list))
真实生活列表包含约300K个字符串条目(每个最多100个字符),考虑到GUI响应时间,上述性能非常差。 我已经描述了我的真实测试用例,它为条目中的每个键输入产生了~0.8秒。
有更快的方法吗?
答案 0 :(得分:1)
如果你正在对包含300,000个项目的普通python列表进行正则表达式模式匹配,那么它自然会很慢。此外,如果您要在列表框中显示300,000个项目,那么显示所有这些项目的速度会很慢。
您最好的选择可能是选择更好的数据结构。例如,在我的系统上,我可以在大约250ms内对300,000个项目运行过滤器,但对具有300,000行的内存中sqlite数据库的查询大约需要一半的时间。在任何一种情况下,如果结果非常大(例如,如果所有300,000都匹配),它可以再添加一秒来完全更新显示器
当然,sqlite并不支持开箱即用的正则表达式,但你可以将一些常见的模式转换为sql模式(例如:' foo。* bar'可以翻译为' ; FOO%酒吧&#39)。有关sqlite和regex的更多信息,请参阅How do I use regex in a SQLite query?
采用的另一种策略是不搜索键入的每个字符。等到用户暂停输入。因此,例如,如果他们键入" Lorem",您就不需要搜索" L"然后" Lo",然后" Lor"等。相反,安排搜索在100毫秒内完成,并且每次按键都可以重新安排搜索。这样可以防止搜索速度变慢,同时仍然为用户提供看似相当快的结果。