1

我有一个字符串,我需要生成一个以给定分隔符结尾的所有子字符串的长度列表。

例如:string = 'a0ddb0gf0', separator = '0',所以我需要生成:lengths = [2,4,3],因为len('a0')==2, len('ddb0')=4 , 和 len('gf0')==3。

我知道它可以通过以下方式完成(例如):

separators = [index for index in range(len(string)) if string[index]==separator]
lengths = [separators[index+1] - separators[index] for index in range(len(separators)-1)]

但我需要它以极快的速度完成(在大量数据上)。为大量数据生成中间列表非常耗时。

有没有一种解决方案可以整齐快速地完成这项工作(py2.7)?

4

5 回答 5

3

最快的?不知道。您可能想对其进行概要分析。

>>> print [len(s) for s in 'a0ddb0gf0'.split('0')]
[1, 3, 2, 0]

而且,如果您真的不想包含零长度字符串:

>>> print [len(s) for s in 'a0ddb0gf0'.split('0') if s]
[1, 3, 2]
于 2012-07-23T00:03:57.560 回答
2

就个人而言,我喜欢itertools.groupby()

>>> from itertools import groupby
>>> sep = '0'
>>> data = 'a0ddb0gf0'
>>> [sum(1 for i in g) for (k, g) in groupby(data, sep.__ne__) if k]
[1, 3, 2]

这根据每个元素是否等于分隔符对数据进行分组,然后获取元素不相等的每个组的长度(通过对组中的每个项目求和 1)。

itertools 函数通常非常快,尽管我不确定比split()这要好多少。我认为强烈支持它的一点是,它可以无缝地处理多个连续出现的分隔符。它还将处理任何可迭代的 for data,而不仅仅是字符串。

于 2012-07-23T00:23:35.310 回答
1

我不知道这会走多快,但这是另一种方式:

def len_pieces(s, sep):
    i = 0
    while True:
        f = s.find(sep, i)
        if f == -1:
            yield len(s) - i
            return
        yield f - i + 1
        i = f + 1
于 2012-07-23T00:10:55.297 回答
0
>>> [len(i) for i in re.findall('.+?0', 'a0ddb0gf0')]
[2, 4, 3]

您可以使用re.finditer来避免中间列表,但在性能上可能没有太大区别:

[len(i.group(0)) for i in re.finditer('.+?0', 'a0ddb0gf0')]
于 2012-07-23T00:07:59.443 回答
0

也许使用重新:

[len(m.group()) for m in re.finditer('(.*?)0', s)]
于 2012-07-23T00:10:34.367 回答