确定多个字符串的公共前缀

96 投票
13 回答
56640 浏览
提问于 2025-04-16 21:40

我有一组字符串,比如:

my_prefix_what_ever
my_prefix_what_so_ever
my_prefix_doesnt_matter

我想找到这些字符串中最长的公共部分,也就是它们的前缀。在上面的例子中,结果应该是:

my_prefix_

这些字符串

my_prefix_what_ever
my_prefix_what_so_ever
my_doesnt_matter

应该得到的前缀是:

my_

有没有一种比较简单的方法可以在Python中找到这个前缀(不需要手动逐个字符去检查)?

附:我使用的是Python 2.6.3。

13 个回答

6

这是我的解决方案:

a = ["my_prefix_what_ever", "my_prefix_what_so_ever", "my_prefix_doesnt_matter"]

prefix_len = len(a[0])
for x in a[1 : ]:
    prefix_len = min(prefix_len, len(x))
    while not x.startswith(a[0][ : prefix_len]):
        prefix_len -= 1

prefix = a[0][ : prefix_len]
22

Ned Batchelder 可能是对的。不过为了好玩,这里有一个更高效的版本,使用了phimuemue 的答案中的 itertools

import itertools

strings = ['my_prefix_what_ever', 
           'my_prefix_what_so_ever', 
           'my_prefix_doesnt_matter']

def all_same(x):
    return all(x[0] == y for y in x)

char_tuples = itertools.izip(*strings)
prefix_tuples = itertools.takewhile(all_same, char_tuples)
''.join(x[0] for x in prefix_tuples)

为了可读性,这里有一个一行的版本 :)

>>> from itertools import takewhile, izip
>>> ''.join(c[0] for c in takewhile(lambda x: all(x[0] == y for y in x), izip(*strings)))
'my_prefix_'
174

不要重新编写已经提供给你的内容:os.path.commonprefix 就是这样做的:

这个功能会返回一个最长的路径前缀(逐个字符比较),这个前缀是列表中所有路径的共同开头。如果列表是空的,它会返回一个空字符串('')。需要注意的是,由于它是逐个字符处理的,所以可能会返回一些无效的路径。

为了和其他回答做个对比,这里是代码:

# Return the longest prefix of all list elements.
def commonprefix(m):
    "Given a list of pathnames, returns the longest common leading component"
    if not m: return ''
    s1 = min(m)
    s2 = max(m)
    for i, c in enumerate(s1):
        if c != s2[i]:
            return s1[:i]
    return s1

撰写回答