如何拆分具有多个分隔符的字符串,但每个分隔符只能拆分一次?python

2024-06-28 14:31:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试拆分一个字符串,例如下面的字符串,并使用下面的所有分隔符,但只拆分一次

string = 'it; seems; like\ta good\tday to watch\va\vmovie.'

delimiters = '\t \v ;'

在这种情况下,输出为:

['it', ' seems; like', 'a good\tday to watch', 'a\vmovie.']

显然,上面的例子是一个毫无意义的例子,但我试图了解这是否可能。是否需要一个相当复杂的正则表达式

如果以前有人问过这个问题,我表示歉意。我做了相当多的搜索,没有找到像我的例子一样的东西。谢谢你的时间


Tags: to字符串stringit例子likewatchgood
3条回答

这应该可以做到:

import re

def split_once_by(s, delims):
    delims = set(delims)
    parts = []
    while delims:
        delim_re = '({})'.format('|'.join(re.escape(d) for d in delims))
        result = re.split(delim_re, s, maxsplit=1)
        if len(result) == 3:
            first, delim, s = result
            parts.append(first)
            delims.remove(delim)
        else:
            break
    
    parts.append(s)
    return parts

例如:

>>> split_once_by('it; seems; like\ta good\tday to watch\va\vmovie.', '\t\v;')
['it', ' seems; like', 'a good\tday to watch', 'a\x0bmovie.']

燃烧酒精的答案启发我写了这个(IMO)更好的函数:

def split_once_by(s, delims):
    split_points = sorted((s.find(d), -len(d), d) for d in delims)
    start = 0
    for stop, _longest_first, d in split_points:
        if stop < start: continue
        yield s[start:stop]
        start = stop + len(d)
    yield s[start:]

使用方法:

>>> list(split_once_by('it; seems; like\ta good\tday to watch\va\vmovie.', '\t\v;'))
['it', ' seems; like', 'a good\tday to watch', 'a\x0bmovie.']

一个简单的算法就可以了

test_string = r'it; seems; like\ta good\tday to watch\va\vmovie.'

delimiters = [r'\t', r'\v', ';']

# find the index of each first occurence and sort it
delimiters = sorted(delimiters, key=lambda delimiter: test_string.find(delimiter))

splitted_string = [test_string]

# perform split with option maxsplit
for index, delimiter in enumerate(delimiters):
    if delimiter in splitted_string[-1]:
        splitted_string += splitted_string[-1].split(delimiter, maxsplit=1)
        splitted_string.pop(index)

print(splitted_string)
# ['it', ' seems; like', 'a good\\tday to watch', 'a\\vmovie.']

只需创建一个模式列表并应用一次:

string = 'it; seems; like\ta good\tday to watch\va\vmovie.'
patterns = ['\t', '\v', ';']

for pattern in patterns:
    string = '*****'.join(string.split(pattern, maxsplit=1)) 

print(string.split('*****'))

输出:

['it', ' seems; like', 'a good\tday to watch', 'a\x0bmovie.']

那么,什么是"*****"

在每次迭代中,当您应用split方法时,您会得到一个列表。因此,在下一次迭代中,您不能应用.split ()方法(因为您有一个列表),因此您必须使用一些奇怪的字符(如"****""@@@""^^^^^^^"或任何您想要的字符)来连接该列表的每个值,以便在下一次迭代中重新应用split()。 最后,对于字符串上的每个"*****",您将有一个列表模式,因此您可以使用它进行最终拆分

相关问题 更多 >