developer tip

문자열을 대문자로 분할

optionbox 2020. 10. 16. 07:22
반응형

문자열을 대문자로 분할


주어진 문자 집합이 발생하기 전에 문자열을 분할하는 비단뱀적인 방법 은 무엇입니까 ?

예를 들어, 'TheLongAndWindingRoad'대문자 (아마도 첫 번째 문자 제외)가 나올 때마다 나누고 ['The', 'Long', 'And', 'Winding', 'Road'].

편집 :에서 그것은 또한 즉, 하나의 발생을 분할해야 'ABC'내가 얻을 싶습니다 ['A', 'B', 'C'].


불행히도 파이썬에서는 너비가 0 인 일치분할 할 수 없습니다 . 그러나 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']

다음은 대체 정규식 솔루션입니다. 문제는 "분할하기 전에 각 대문자 앞에 공백을 삽입하는 방법"으로 다시 표현할 수 있습니다.

>>> s = "TheLongAndWindingRoad ABC A123B45"
>>> re.sub( r"([A-Z])", r" \1", s).split()
['The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']

이것은 대부분의 다른 솔루션이 그렇지 않은 모든 비 공백 문자를 보존하는 이점이 있습니다.


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

rexeg를 변경 하기 "It'sATest"위해 분할 ["It's", 'A', 'Test']하려면"[A-Z][a-z']*"


@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

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

또는

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

src = 'TheLongAndWindingRoad'
glue = ' '

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

대체 솔루션 (명시 적 정규식을 싫어하는 경우) :

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

정규식이없고 원하는 경우 연속 대문자를 유지할 수있는 기능

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

이것은 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'I 'd like to get ['A', 'B', 'C'].

iterable = "ABC"
[ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())]
# ['A', 'B', 'C']

more_itertools는 모든 원래 itertools 레시피에 대한 구현을 포함하여 60 개 이상의 유용한 도구가 포함 된 타사 패키지로 , 수동 구현을 제거합니다.


미리보기 사용 :

Python 3.7에서는 다음을 수행 할 수 있습니다.

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

그리고 결과 :

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

정규식 또는 열거를 사용하지 않는 다른 방법 :

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

너무 많은 메서드를 연결하거나 읽기 어려울 수있는 긴 목록 이해를 사용하지 않고 더 명확하고 간단하다고 생각합니다.


An alternate way using enumerate and isupper()

Code:

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

Output:

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

Sharing what came to mind when I read the post. Different from other posts.

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

Pythonic way could be:

"".join([(" "+i if i.isupper() else i) for i in 'TheLongAndWindingRoad']).strip().split()
['The', 'Long', 'And', 'Winding', 'Road']

Works good for Unicode, avoiding re/re2.

"".join([(" "+i if i.isupper() else i) for i in 'СуперМаркетыПродажаКлиент']).strip().split()
['Супер', 'Маркеты', 'Продажа', 'Клиент']

Replace every uppercase letter 'L' in the given with an empty space plus that letter " L". We can do this using list comprehension or we can define a function to do it as follows.

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

If you choose to go by a function, here is how.

def splitAtUpperCase(text):
    result = ""
    for char in text:
        if char.isupper():
            result += " " + char
        else:
            result += char
    return result.split()

In the case of the given example:

print(splitAtUpperCase('TheLongAndWindingRoad')) 
>>>['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road']

But most of the time that we are splitting a sentence at upper case letters, it is usually the case that we want to maintain abbreviations that are typically a continuous stream of uppercase letters. The code below would help.

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

Thanks.

참고URL : https://stackoverflow.com/questions/2277352/split-a-string-at-uppercase-letters

반응형