在Python中执行多个字符串替换的最快实现

时间:2010-08-05 00:54:57

标签: php python string

除了对字符串执行'replace'链接之外,是否有任何推荐的方法可以进行多个字符串替换(即text.replace(a,b).replace(c,d).replace(e,f)... )? 例如,您如何实现一个快速的函数,其行为类似于Python中的PHP htmlspecialchars?

我比较了(1)多个'替换'方法,(2)正则表达式方法,以及(3)马特安德森的方法。

n = 10次运行后,结果显示如下:

100个字符:

TIME: 0 ms [ replace_method(str) ]
TIME: 5 ms [ regular_expression_method(str, dict) ]
TIME: 1 ms [ matts_multi_replace_method(list, str) ]

1000个字符:

TIME: 0 ms [ replace_method(str) ]
TIME: 3 ms [ regular_expression_method(str, dict) ]
TIME: 2 ms [ matts_multi_replace_method(list, str) ]

10000个字符:

TIME: 3 ms [ replace_method(str) ]
TIME: 7 ms [ regular_expression_method(str, dict) ]
TIME: 5 ms [ matts_multi_replace_method(list, str) ]

在100000个字符上:

TIME: 36 ms [ replace_method(str) ]
TIME: 46 ms [ regular_expression_method(str, dict) ]
TIME: 39 ms [ matts_multi_replace_method(list, str) ]

在1000000个字符上:

TIME: 318 ms [ replace_method(str) ]
TIME: 360 ms [ regular_expression_method(str, dict) ]
TIME: 320 ms [ matts_multi_replace_method(list, str) ]

在3687809个字符上:

TIME: 1.277524 sec [ replace_method(str) ]
TIME: 1.290590 sec [ regular_expression_method(str, dict) ]
TIME: 1.116601 sec [ matts_multi_replace_method(list, str) ]

对Matt在相当大的输入字符串上击败多'replace'方法感到荣幸。

任何人都有想法用较小的字符串击败它吗?

3 个答案:

答案 0 :(得分:4)

可能会出现以下情况?使用要替换的第一个“from”项目将文本拆分为多个部分,然后递归地将每个部分拆分为子部分,并使用下一个要替换的“from”项目,依此类推,直到您访问了所有替换项目为止。然后在递归函数完成时,为每个“to”替换项加入。

有点难以绕过下面的代码(这对我来说,我写了它),但似乎按预期运行。我没有对它进行基准测试,但我怀疑它会相当快。

def multi_replace(pairs, text):
    stack = list(pairs)
    stack.reverse()
    def replace(stack, parts):
        if not stack:
            return parts
        # copy the stack so I don't disturb parallel recursions
        stack = list(stack) 
        from_, to = stack.pop()
        #print 'split (%r=>%r)' % (from_, to), parts
        split_parts = [replace(stack, part.split(from_)) for part in parts]
        parts = [to.join(split_subparts) for split_subparts in split_parts]
        #print 'join (%r=>%r)' % (from_, to), parts
        return parts
    return replace(stack, [text])[0]


print multi_replace(
    [('foo', 'bar'), ('baaz', 'foo'), ('quux', 'moop')], 
    'foobarbaazfooquuxquux')

有:

barbarfoobarmoopmoop

答案 1 :(得分:1)

通常,.replace方法胜过所有其他方法。 (见上面的基准测试。)

答案 2 :(得分:0)

多快?另外,你的琴弦有多大?

有一个相当简单的recipe用于构建正则表达式以在另一个站点上完成工作。可能需要一些调整来处理正则表达式元字符;我看得太近了。

如果这还不够好,你可能需要写一些C代码,老实说。您可以构建一个简单的状态机来执行所有替换,然后逐字节处理任何字符串,而不会沿着机器进行回溯以实际执行工作。但是,我怀疑你会在没有使用C并优化它的情况下击败正则表达式引擎。