按大写字母拆分字符串
- 2025-02-21 08:48:00
- admin 原创
- 25
问题描述:
在给定的一组字符出现之前拆分字符串的 Python方法是什么?
例如,我想 'TheLongAndWindingRoad'
在出现任何大写字母时进行拆分(可能除了第一个),并获得['The', 'Long', 'And', 'Winding', 'Road']
。
编辑:它还应该拆分单个事件,即'ABC'
我想要获得的['A', 'B', 'C']
。
解决方案 1:
不幸的是,在 Python 中无法根据零宽度匹配进行拆分re.findall
。但你可以改用:
>>> import re
>>> re.findall('[A-Z][^A-Z]*', 'TheLongAndWindingRoad')
['The', 'Long', 'And', 'Winding', 'Road']
>>> re.findall('[A-Z][^A-Z]*', 'ABC')
['A', 'B', 'C']
解决方案 2:
以下是另一种正则表达式解决方案。该问题可以重新表述为“如何在拆分之前在每个大写字母前插入一个空格”:
>>> s = "TheLongAndWindingRoad ABC A123B45"
>>> re.sub( r"([A-Z])", r" ", s).split()
['The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']
这样做的好处是可以保留所有非空白字符,而大多数其他解决方案则做不到。
解决方案 3:
使用前瞻和后瞻:
在 Python 3.7 中,你可以执行以下操作:
re.split('(?<=.)(?=[A-Z])', 'TheLongAndWindingRoad')
结果是:
['The', 'Long', 'And', 'Winding', 'Road']
您需要进行后视检查以避免开头出现空字符串。
解决方案 4:
>>> import re
>>> re.findall('[A-Z][a-z]*', 'TheLongAndWindingRoad')
['The', 'Long', 'And', 'Winding', 'Road']
>>> re.findall('[A-Z][a-z]*', 'SplitAString')
['Split', 'A', 'String']
>>> re.findall('[A-Z][a-z]*', 'ABC')
['A', 'B', 'C']
如果你想"It'sATest"
拆分以将["It's", 'A', 'Test']
rexeg 更改为"[A-Z][a-z']*"
解决方案 5:
我认为更好的答案可能是将字符串拆分成不以大写字母结尾的单词。这样可以处理字符串不以大写字母开头的情况。
re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoad')
例子:
>>> import re
>>> re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoadABC')
['about', 'The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C']
解决方案 6:
@ChristopheD 解决方案的变体
s = 'TheLongAndWindingRoad'
pos = [i for i,e in enumerate(s+'A') if e.isupper()]
parts = [s[pos[j]:pos[j+1]] for j in xrange(len(pos)-1)]
print parts
解决方案 7:
Pythonic 方式可能是:
"".join([(" "+i if i.isupper() else i) for i in 'TheLongAndWindingRoad']).strip().split()
['The', 'Long', 'And', 'Winding', 'Road']
适用于 Unicode,避免使用 re/re2。
"".join([(" "+i if i.isupper() else i) for i in 'СуперМаркетыПродажаКлиент']).strip().split()
['Супер', 'Маркеты', 'Продажа', 'Клиент']
解决方案 8:
import re
filter(None, re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad"))
或者
[s for s in re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad") if s]
解决方案 9:
src = 'TheLongAndWindingRoad'
glue = ' '
result = ''.join(glue + x if x.isupper() else x for x in src).strip(glue).split(glue)
解决方案 10:
另一个无需正则表达式,但能够根据需要保持连续大写字母的功能
def split_on_uppercase(s, keep_contiguous=False):
"""
Args:
s (str): string
keep_contiguous (bool): flag to indicate we want to
keep contiguous uppercase chars together
Returns:
"""
string_length = len(s)
is_lower_around = (lambda: s[i-1].islower() or
string_length > (i + 1) and s[i + 1].islower())
start = 0
parts = []
for i in range(1, string_length):
if s[i].isupper() and (not keep_contiguous or is_lower_around()):
parts.append(s[start: i])
start = i
parts.append(s[start:])
return parts
>>> split_on_uppercase('theLongWindingRoad')
['the', 'Long', 'Winding', 'Road']
>>> split_on_uppercase('TheLongWindingRoad')
['The', 'Long', 'Winding', 'Road']
>>> split_on_uppercase('TheLongWINDINGRoadT', True)
['The', 'Long', 'WINDING', 'Road', 'T']
>>> split_on_uppercase('ABC')
['A', 'B', 'C']
>>> split_on_uppercase('ABCD', True)
['ABCD']
>>> split_on_uppercase('')
['']
>>> split_on_uppercase('hello world')
['hello world']
解决方案 11:
替代解决方案(如果您不喜欢明确的正则表达式):
s = 'TheLongAndWindingRoad'
pos = [i for i,e in enumerate(s) if e.isupper()]
parts = []
for j in xrange(len(pos)):
try:
parts.append(s[pos[j]:pos[j+1]])
except IndexError:
parts.append(s[pos[j]:])
print parts
解决方案 12:
将给定中的每个大写字母“L”替换为空格加上字母“L”。我们可以使用列表推导来做到这一点,也可以定义一个函数来做到这一点,如下所示。
s = 'TheLongANDWindingRoad ABC A123B45'
''.join([char if (char.islower() or not char.isalpha()) else ' '+char for char in list(s)]).strip().split()
>>> ['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']
如果您选择按功能操作,请按以下步骤操作。
def splitAtUpperCase(text):
result = ""
for char in text:
if char.isupper():
result += " " + char
else:
result += char
return result.split()
就给定的例子而言:
print(splitAtUpperCase('TheLongAndWindingRoad'))
>>>['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road']
但大多数情况下,当我们以大写字母拆分句子时,通常我们希望保留缩写,这些缩写通常是连续的大写字母流。下面的代码会有所帮助。
def splitAtUpperCase(s):
for i in range(len(s)-1)[::-1]:
if s[i].isupper() and s[i+1].islower():
s = s[:i]+' '+s[i:]
if s[i].isupper() and s[i-1].islower():
s = s[:i]+' '+s[i:]
return s.split()
splitAtUpperCase('TheLongANDWindingRoad')
>>> ['The', 'Long', 'AND', 'Winding', 'Road']
谢谢。
解决方案 13:
def solution(s):
st = ''
for c in s:
if c == c.upper():
st += ' '
st += c
return st
解决方案 14:
我根据大写字母拆分的解决方案 - 保留大写单词
text = 'theLongAndWindingRoad ABC'
result = re.sub('(?<=.)(?=[A-Z][a-z])', r" ", text).split()
print(result)
#['the', 'Long', 'And', 'Winding', 'Road', 'ABC']
解决方案 15:
不使用正则表达式或枚举的另一种方法:
word = 'TheLongAndWindingRoad'
list = [x for x in word]
for char in list:
if char != list[0] and char.isupper():
list[list.index(char)] = ' ' + char
fin_list = ''.join(list).split(' ')
我认为它更清晰、更简单,不需要链接太多方法或使用难以阅读的长列表理解。
解决方案 16:
使用该工具可以实现这一点more_itertools.split_before
。
import more_itertools as mit
iterable = "TheLongAndWindingRoad"
[ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())]
# ['The', 'Long', 'And', 'Winding', 'Road']
它还应该拆分单个事件,即从
'ABC'
我想要获得的['A', 'B', 'C']
。
iterable = "ABC"
[ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())]
# ['A', 'B', 'C']
more_itertools
是一个第三方包,包含 60 多个有用的工具,包括所有原始itertools 配方的实现,从而无需手动实现。
解决方案 17:
你可能还想这样做
def camelcase(s):
words = []
for char in s:
if char.isupper():
words.append(':'+char)
else:
words.append(char)
words = ((''.join(words)).split(':'))
return len(words)
这将输出如下
s = 'oneTwoThree'
print(camecase(s)
//['one', 'Two', 'Three']
解决方案 18:
我正在使用列表
def split_by_upper(x):
i = 0
lis = list(x)
while True:
if i == len(lis)-1:
if lis[i].isupper():
lis.insert(i,",")
break
if lis[i].isupper() and i != 0:
lis.insert(i,",")
i+=1
i+=1
return "".join(lis).split(",")
输出:
data = "TheLongAndWindingRoad"
print(split_by_upper(data))`
>> ['The', 'Long', 'And', 'Winding', 'Road']
解决方案 19:
聚会有点迟了,但是:
In [1]: camel = "CamelCaseConfig"
In [2]: parts = "".join([
f"|{c}" if c.isupper() else c
for c in camel
]).lstrip("|").split("|")
In [3]: screaming_snake = "_".join([
part.upper()
for part in parts
])
In [4]: screaming_snake
Out[4]: 'CAMEL_CASE_CONFIG'
我的部分回答是基于其他人的回答
解决方案 20:
def split_string_after_upper_case(word):
word_lst = [x for x in word]
index = 0
for char in word[1:]:
index += 1
if char.isupper():
word_lst.insert(index, ' ')
index += 1
return ''.join(word_lst).split(" ")
k = split_string_after_upper_case('TheLongAndWindingRoad')
print(k)
解决方案 21:
另一种方法是enumerate
使用isupper()
代码:
strs = 'TheLongAndWindingRoad'
ind =0
count =0
new_lst=[]
for index, val in enumerate(strs[1:],1):
if val.isupper():
new_lst.append(strs[ind:index])
ind=index
if ind<len(strs):
new_lst.append(strs[ind:])
print new_lst
输出:
['The', 'Long', 'And', 'Winding', 'Road']
解决方案 22:
分享我读到这篇文章时想到的东西。与其他帖子不同。
strs = 'TheLongAndWindingRoad'
# grab index of uppercase letters in strs
start_idx = [i for i,j in enumerate(strs) if j.isupper()]
# create empty list
strs_list = []
# initiate counter
cnt = 1
for pos in start_idx:
start_pos = pos
# use counter to grab next positional element and overlook IndexeError
try:
end_pos = start_idx[cnt]
except IndexError:
continue
# append to empty list
strs_list.append(strs[start_pos:end_pos])
cnt += 1