簡體   English   中英

如何拆分具有多個定界符的字符串,但每個定界符僅一次? Python

[英]How do I split a string with several delimiters, but only once on each delimiter? Python

我正在嘗試拆分一個字符串,例如下面的字符串,所有分隔符都在下面,但只有一次。

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

delimiters = '\t \v;'

在這種情況下,output 將是:

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

顯然上面的例子是一個無意義的例子,但我試圖了解這是否可能。 一個相當復雜的正則表達式是否合適?

如果之前有人問過這個問題,我們深表歉意。 我進行了相當多的搜索,但找不到與我的示例非常相似的東西。 謝謝你的時間!

這應該可以解決問題:

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.']

Burning Alcohol 的回答啟發了我更好地寫這個(IMO)function:

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.']

只需創建一個模式列表並應用它們一次:

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('*****'))

Output:

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

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

在每次迭代中,當您應用split方法時,您會得到一個列表。 因此,在下一次迭代中,您不能應用.split ()方法(因為您有一個列表),因此您必須將該列表的每個值與一些奇怪的字符連接起來,例如"****""@@@""^^^^^^^"或任何您想要的,以便在下一次迭代中重新應用 split ()。 最后,對於字符串中的每個"*****" ,您將擁有一個列表模式,因此您可以使用它來進行最終拆分。

一個簡單的算法就可以了,

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.']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM