Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在元组列表中搜索匹配子字符串的算法方法?_Python_Algorithm_Substring_String Matching_Aho Corasick - Fatal编程技术网

Python 在元组列表中搜索匹配子字符串的算法方法?

Python 在元组列表中搜索匹配子字符串的算法方法?,python,algorithm,substring,string-matching,aho-corasick,Python,Algorithm,Substring,String Matching,Aho Corasick,我有一个元组列表,大约10万个条目。每个元组由一个id和一个字符串组成,我的目标是列出元组的id,其字符串包含给定子字符串列表中的一个子字符串。 我目前的解决方案是通过集合理解,ids可以重复 tuples = [(id1, 'cheese trees'), (id2, 'freezy breeze'),...] vals = ['cheese', 'flees'] ids = {i[0] for i in tuples if any(val in i[1] for val in vals)}

我有一个元组列表,大约10万个条目。每个元组由一个id和一个字符串组成,我的目标是列出元组的id,其字符串包含给定子字符串列表中的一个子字符串。 我目前的解决方案是通过集合理解,ids可以重复

tuples = [(id1, 'cheese trees'), (id2, 'freezy breeze'),...]
vals = ['cheese', 'flees']
ids = {i[0] for i in tuples if any(val in i[1] for val in vals)}

output: {id1}

有没有一种算法可以让你更快的完成?我对精确的子串匹配感兴趣,也可能对近似的子串匹配感兴趣。我在这里追求的主要东西是一种算法,它可以提供比理解更快的速度优势。

免责声明我是

对于精确匹配的情况,解决此问题的一种方法是使用注释中提到的。是一个生成Trie正则表达式(正则表达式格式的Trie)的库,可与Python的正则表达式引擎结合使用:

import random
import pandas as pd
import trrex as tx
import re

df = pd.read_csv('jeopardy-small.csv')
with open('words-sample') as infile:
    words = [line.strip() for line in infile]


tuples = [(random.randint(1, 250), sentence) for sentence in df['question']]


def fun_kislyuk(ws, ts):
    return {t[0] for t in ts if any(w in t[1] for w in ws)}


def fun_trrex(ws, ts):
    pattern = re.compile(tx.make(ws, left='', right=''))
    return {i for i, s in ts if pattern.search(s)}


if __name__ == "__main__":
    print(fun_trrex(words, tuples) == fun_kislyuk(words, tuples))
输出

True
上述功能的计时为:

%timeit fun_trrex(words, tuples)
11.3 ms ± 34.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit fun_kislyuk(words, tuples)
67.5 ms ± 1.75 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
数据是一份由《危险》杂志提出的大约2千个问题和500个随机选择的单词组成的列表。你可以找到复制实验的资源

更新

如果添加注释中提到的分组策略,则时间改进会增加,以下是功能:

def fun_grouping_trrex(ws, ts):
    pattern = re.compile(tx.make(ws, left='', right=''))
    groups = defaultdict(list)
    for i, s in ts:
        groups[i].append(s)

    return {i for i, vs in groups.items() if any(pattern.search(v) for v in vs)}
以及时间安排:

%timeit fun_trrex(words, tuples)
11.2 ms ± 61.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit fun_grouping_trrex(words, tuples)
4.96 ms ± 320 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit fun_kislyuk(words, tuples)
67.4 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

分组+trrex的方法可使性能提高约10倍。但最后一个结果是有保留的,因为它非常依赖于数据集。

什么是近似子字符串匹配?什么是“算法方法”?有一种称为近似字符串匹配的方法。据我所知,Python的一个实现是。@martineau虽然FuzzyWuzzy对单个字符串进行近似字符串匹配,但它并没有提高处理大量字符串的速度,这是我的主要观点。两个小点:(1)可以通过多处理来加快速度。(2) 如果按ID分组,则只需处理一个组,直到它找到第一个匹配项(可能会节省一些时间)。