• <bdo id='YHrQj'></bdo><ul id='YHrQj'></ul>
  1. <small id='YHrQj'></small><noframes id='YHrQj'>

    <legend id='YHrQj'><style id='YHrQj'><dir id='YHrQj'><q id='YHrQj'></q></dir></style></legend>
    <tfoot id='YHrQj'></tfoot>

      <i id='YHrQj'><tr id='YHrQj'><dt id='YHrQj'><q id='YHrQj'><span id='YHrQj'><b id='YHrQj'><form id='YHrQj'><ins id='YHrQj'></ins><ul id='YHrQj'></ul><sub id='YHrQj'></sub></form><legend id='YHrQj'></legend><bdo id='YHrQj'><pre id='YHrQj'><center id='YHrQj'></center></pre></bdo></b><th id='YHrQj'></th></span></q></dt></tr></i><div id='YHrQj'><tfoot id='YHrQj'></tfoot><dl id='YHrQj'><fieldset id='YHrQj'></fieldset></dl></div>

      查找最佳子字符串匹配

      时间:2024-08-21

        <tbody id='vLdXg'></tbody>
      <legend id='vLdXg'><style id='vLdXg'><dir id='vLdXg'><q id='vLdXg'></q></dir></style></legend>
            • <bdo id='vLdXg'></bdo><ul id='vLdXg'></ul>

              <i id='vLdXg'><tr id='vLdXg'><dt id='vLdXg'><q id='vLdXg'><span id='vLdXg'><b id='vLdXg'><form id='vLdXg'><ins id='vLdXg'></ins><ul id='vLdXg'></ul><sub id='vLdXg'></sub></form><legend id='vLdXg'></legend><bdo id='vLdXg'><pre id='vLdXg'><center id='vLdXg'></center></pre></bdo></b><th id='vLdXg'></th></span></q></dt></tr></i><div id='vLdXg'><tfoot id='vLdXg'></tfoot><dl id='vLdXg'><fieldset id='vLdXg'></fieldset></dl></div>
              <tfoot id='vLdXg'></tfoot>

                <small id='vLdXg'></small><noframes id='vLdXg'>

              1. 本文介绍了查找最佳子字符串匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我正在寻找使用现有库(difflibfuzzywuzzypython-levenshtein)的库或方法,以便在文本(corpus)中查找字符串(query)的最匹配项

                我开发了一个基于difflib的方法,将corpus拆分成大小为n(长度为query)的ngram。

                import difflib
                from nltk.util import ngrams
                
                def get_best_match(query, corpus):
                    ngs = ngrams( list(corpus), len(query) )
                    ngrams_text = [''.join(x) for x in ngs]
                    return difflib.get_close_matches(query, ngrams_text, n=1, cutoff=0)
                

                当查询和匹配字符串之间的差异只是字符替换时,它可以按我希望的方式工作。

                query = "ipsum dolor"
                corpus = "lorem 1psum d0l0r sit amet"
                
                match = get_best_match(query, corpus)
                # match = "1psum d0l0r"
                

                但如果区别是字符删除,则不是。

                query = "ipsum dolor"
                corpus = "lorem 1psum dlr sit amet"
                
                match = get_best_match(query, corpus)
                # match = "psum dlr si"
                # expected_match = "1psum dlr"
                

                有没有办法获得更灵活的结果大小(如expected_match)?

                编辑%1:

                • 此脚本的实际用途是将查询(字符串)与 OCR输出混乱。
                • 正如我在问题中所说,OCR可能会混淆字符,甚至会遗漏字符。
                • 如果可能,还要考虑单词之间缺少空格的情况。
                • 最佳匹配是指不包括来自查询上的字符以外的其他单词的字符。

                编辑2:

                我现在使用的解决方案是使用(n-k)-grams for k = {1,2,3}扩展ngram以防止3次删除。它比第一个版本好得多,但在速度方面效率不高,因为我们要检查的ngram数量是第一个版本的3倍多。它也是一个不可概括的解决方案。

                推荐答案

                此函数查找可变长度的最佳匹配子字符串

                该实现将语料库视为一个长字符串,从而避免您担心空格和未分隔的单词。

                代码摘要: 1.step的步长扫描语料库中的匹配值,以查找最高匹配值的大致位置pos2.通过调整子字符串的左/右位置,查找pos附近匹配值最高的子字符串。

                from difflib import SequenceMatcher
                
                def get_best_match(query, corpus, step=4, flex=3, case_sensitive=False, verbose=False):
                    """Return best matching substring of corpus.
                
                    Parameters
                    ----------
                    query : str
                    corpus : str
                    step : int
                        Step size of first match-value scan through corpus. Can be thought of
                        as a sort of "scan resolution". Should not exceed length of query.
                    flex : int
                        Max. left/right substring position adjustment value. Should not
                        exceed length of query / 2.
                
                    Outputs
                    -------
                    output0 : str
                        Best matching substring.
                    output1 : float
                        Match ratio of best matching substring. 1 is perfect match.
                    """
                
                    def _match(a, b):
                        """Compact alias for SequenceMatcher."""
                        return SequenceMatcher(None, a, b).ratio()
                
                    def scan_corpus(step):
                        """Return list of match values from corpus-wide scan."""
                        match_values = []
                
                        m = 0
                        while m + qlen - step <= len(corpus):
                            match_values.append(_match(query, corpus[m : m-1+qlen]))
                            if verbose:
                                print(query, "-", corpus[m: m + qlen], _match(query, corpus[m: m + qlen]))
                            m += step
                
                        return match_values
                
                    def index_max(v):
                        """Return index of max value."""
                        return max(range(len(v)), key=v.__getitem__)
                
                    def adjust_left_right_positions():
                        """Return left/right positions for best string match."""
                        # bp_* is synonym for 'Best Position Left/Right' and are adjusted 
                        # to optimize bmv_*
                        p_l, bp_l = [pos] * 2
                        p_r, bp_r = [pos + qlen] * 2
                
                        # bmv_* are declared here in case they are untouched in optimization
                        bmv_l = match_values[p_l // step]
                        bmv_r = match_values[p_l // step]
                
                        for f in range(flex):
                            ll = _match(query, corpus[p_l - f: p_r])
                            if ll > bmv_l:
                                bmv_l = ll
                                bp_l = p_l - f
                
                            lr = _match(query, corpus[p_l + f: p_r])
                            if lr > bmv_l:
                                bmv_l = lr
                                bp_l = p_l + f
                
                            rl = _match(query, corpus[p_l: p_r - f])
                            if rl > bmv_r:
                                bmv_r = rl
                                bp_r = p_r - f
                
                            rr = _match(query, corpus[p_l: p_r + f])
                            if rr > bmv_r:
                                bmv_r = rr
                                bp_r = p_r + f
                
                            if verbose:
                                print("
                " + str(f))
                                print("ll: -- value: %f -- snippet: %s" % (ll, corpus[p_l - f: p_r]))
                                print("lr: -- value: %f -- snippet: %s" % (lr, corpus[p_l + f: p_r]))
                                print("rl: -- value: %f -- snippet: %s" % (rl, corpus[p_l: p_r - f]))
                                print("rr: -- value: %f -- snippet: %s" % (rl, corpus[p_l: p_r + f]))
                
                        return bp_l, bp_r, _match(query, corpus[bp_l : bp_r])
                
                    if not case_sensitive:
                        query = query.lower()
                        corpus = corpus.lower()
                
                    qlen = len(query)
                
                    if flex >= qlen/2:
                        print("Warning: flex exceeds length of query / 2. Setting to default.")
                        flex = 3
                
                    match_values = scan_corpus(step)
                    pos = index_max(match_values) * step
                
                    pos_left, pos_right, match_value = adjust_left_right_positions()
                
                    return corpus[pos_left: pos_right].strip(), match_value
                

                示例:

                query = "ipsum dolor"
                corpus = "lorem i psum d0l0r sit amet"
                match = get_best_match(query, corpus, step=2, flex=4)
                print(match)
                ('i psum d0l0r', 0.782608695652174)
                

                一些好的启发式建议是始终保留step < len(query) * 3/4flex < len(query) / 3。我还增加了区分大小写的功能,以防这很重要。当您开始使用步长和伸缩值时,它可以很好地工作。步长值越小,结果越好,但计算时间越长。Flex控制允许结果子字符串的长度的灵活性。

                重要说明:这将只找到第一个最佳匹配,因此如果有多个同样好的匹配,则只会返回第一个。若要允许多个匹配,请更改index_max()以返回输入列表的n最高值的索引列表,并循环该列表中的值的adjust_left_right_positions()

                这篇关于查找最佳子字符串匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:如何使用纯Python激活Google CoLab GPU 下一篇:Python pandas 根据标题值匹配VLOOKUP列

                相关文章

              2. <i id='DwnBp'><tr id='DwnBp'><dt id='DwnBp'><q id='DwnBp'><span id='DwnBp'><b id='DwnBp'><form id='DwnBp'><ins id='DwnBp'></ins><ul id='DwnBp'></ul><sub id='DwnBp'></sub></form><legend id='DwnBp'></legend><bdo id='DwnBp'><pre id='DwnBp'><center id='DwnBp'></center></pre></bdo></b><th id='DwnBp'></th></span></q></dt></tr></i><div id='DwnBp'><tfoot id='DwnBp'></tfoot><dl id='DwnBp'><fieldset id='DwnBp'></fieldset></dl></div>
              3. <tfoot id='DwnBp'></tfoot>

              4. <small id='DwnBp'></small><noframes id='DwnBp'>

                  <legend id='DwnBp'><style id='DwnBp'><dir id='DwnBp'><q id='DwnBp'></q></dir></style></legend>

                    • <bdo id='DwnBp'></bdo><ul id='DwnBp'></ul>