web-dev-qa-db-ja.com

文字列を大文字で分割します

Pythonic 指定された文字セットが出現する前に文字列を分割する方法は何ですか?

たとえば、'TheLongAndWindingRoad'大文字が出現した場合(最初の文字を除く場合があります)、['The', 'Long', 'And', 'Winding', 'Road']

編集:また、単一のオカレンスを分割する必要があります。つまり、'ABC'入手したい['A', 'B', 'C']

74

残念ながら、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']
112
Mark Byers

代替正規表現ソリューションは次のとおりです。この問題は、「分割を行う前に、各大文字の前にスペースを挿入するにはどうすればよいか」と言い換えることができます。

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

これには、他のほとんどのソリューションが保持していないすべての非空白文字を保持するという利点があります。

24
Dave Kirby
>>> 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']*"に変更します

17
John La Rooy

@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
6
pwdyson
import re
filter(None, re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad"))

または

[s for s in re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad") if s]
4
Gabe
src = 'TheLongAndWindingRoad'
glue = ' '

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

代替ソリューション(明示的な正規表現が嫌いな場合):

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
2
ChristopheD

これは 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 は、元のすべての itertools recipes の実装を含む60以上の便利なツールを備えたサードパーティのパッケージであり、手動実装を不要にします。

1
pylang

正規表現のない別のものと、必要に応じて連続した大文字を保持する機能

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

投稿を読んだときに思いついたことを共有します。他の投稿とは異なります。

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
0
Do L.

先読みを使用します。

Python 3.7では、これを行うことができます。

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

そして、それは以下をもたらします:

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

enumerateisupper()を使用する代替方法

コード:

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

正規表現または列挙を使用しない代替方法:

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

あまりにも多くのメソッドをチェーンしたり、読みづらい可能性のある長いリストの理解を使用したりすることなく、より明確でシンプルになったと思います。

0
Pie 'Oh' Pah