Подтвердить что ты не робот

Разделить строку заглавными буквами

Как питонный способ разбить строку перед появлением заданного набора символов?

Например, я хочу разделить 'TheLongAndWindingRoad' при любом появлении заглавной буквы (возможно, кроме первой) и получить ['The', 'Long', 'And', 'Winding', 'Road'].

Редактировать: он также должен разделять отдельные экземпляры, т.е. из 'ABC' я хотел бы получить ['A', 'B', 'C'].

4b9b3361

Ответ 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" \1", s).split()
['The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']

Это имеет то преимущество, что сохраняются все символы без пробелов, которых нет в большинстве других решений.

Ответ 3

>>> 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']*"

Ответ 4

Изменение на решении @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

Ответ 5

import re
filter(None, re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad"))

или

[s for s in re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad") if s]

Ответ 6

src = 'TheLongAndWindingRoad'
glue = ' '

result = ''.join(glue + x if x.isupper() else x for x in src).strip(glue).split(glue)

Ответ 7

Альтернативное решение (если вам не нравятся явные регулярные выражения):

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

Ответ 8

Другое без регулярного выражения и возможность сохранять смежный прописной, если требуется

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

Ответ 9

Это возможно с more_itertools.split_before инструмента 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, что исключает их ручную реализацию.

Ответ 10

Используйте взгляд в будущее:

В Python 3.7 вы можете сделать это:

re.split('(?=[A-Z])', 'theLongAndWindingRoad')

И это дает:

['the', 'Long', 'And', 'Winding', 'Road']

Ответ 11

Альтернативный способ без использования регулярного выражения или перечисления:

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

Я думаю, что это проще и проще, не связывая слишком много методов или используя длинное понимание списка, которое может быть трудно читать.

Ответ 12

Альтернативный способ: 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']

Ответ 13

Поделиться тем, что пришло в голову, когда я прочитал пост. Отличается от других постов.

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

Ответ 14

Питонический путь может быть:

"".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()
['Супер', 'Маркеты', 'Продажа', 'Клиент']

Ответ 15

Замените каждую заглавную букву "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']

Благодарю.