Apa cara pythonic untuk memisahkan string sebelum kemunculan sekumpulan karakter tertentu?
Misalnya, saya ingin membagi
'TheLongAndWindingRoad'
setiap kejadian huruf besar (mungkin kecuali yang pertama), dan mendapatkan
['The', 'Long', 'And', 'Winding', 'Road']
.
Sunting: Ini juga harus membagi kejadian tunggal, yaitu dari 'ABC'
saya ingin mendapatkan
['A', 'B', 'C']
.
'[a-zA-Z][^A-Z]*'
sebagai regex.print(re.findall('^[a-z]+|[A-Z][^A-Z]*', 'theLongAndWindingRoad'))
Berikut adalah solusi regex alternatif. Masalahnya dapat dirumuskan ulang sebagai "bagaimana cara menyisipkan spasi sebelum setiap huruf besar, sebelum melakukan pemisahan":
>>> s = "TheLongAndWindingRoad ABC A123B45" >>> re.sub( r"([A-Z])", r" \1", s).split() ['The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']
Ini memiliki keuntungan dalam mempertahankan semua karakter non-spasi, yang kebanyakan solusi lain tidak.
sumber
>>> 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']
Jika Anda ingin
"It'sATest"
membagi untuk["It's", 'A', 'Test']
mengubah rexeg menjadi"[A-Z][a-z']*"
sumber
drops
semua kata biasa (hanya alfa biasa) yang tidak dimulai dengan huruf besar. Saya ragu itu maksud OP.Variasi solusi @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
sumber
Gunakan lookahead:
Di Python 3.7, Anda dapat melakukan ini:
re.split('(?=[A-Z])', 'theLongAndWindingRoad')
Dan itu menghasilkan:
['the', 'Long', 'And', 'Winding', 'Road']
sumber
import re filter(None, re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad"))
atau
[s for s in re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad") if s]
sumber
[s for s in re.compile(r"([A-Z][^A-Z]*)").split( "TheLongAndWindingRoad") if s]
memberi['The', 'Long', 'And', 'Winding', 'Road']
filter
ini sama dengan pemahaman daftar dengan kondisi. Apakah Anda menentangnya?filter(lambdaconditionfunc, ...)
b) di Python 3,filter()
mengembalikan sebuah iterator. Jadi mereka tidak akan setara sepenuhnya. c) Saya perkirakanfilter()
lebih lambat jugaSaya pikir jawaban yang lebih baik mungkin adalah membagi string menjadi kata-kata yang tidak diakhiri dengan huruf kapital. Ini akan menangani kasus di mana string tidak dimulai dengan huruf kapital.
re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoad')
contoh:
>>> import re >>> re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoadABC') ['about', 'The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C']
sumber
src = 'TheLongAndWindingRoad' glue = ' ' result = ''.join(glue + x if x.isupper() else x for x in src).strip(glue).split(glue)
sumber
Solusi alternatif (jika Anda tidak menyukai ekspresi reguler):
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
sumber
Lain tanpa regex dan kemampuan untuk menjaga huruf besar jika diinginkan
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']
sumber
Ini dimungkinkan dengan
more_itertools.split_before
alat tersebut.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']
iterable = "ABC" [ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())] # ['A', 'B', 'C']
more_itertools
adalah paket pihak ketiga dengan 60+ alat berguna termasuk implementasi untuk semua resep itertools asli , yang meniadakan implementasi manualnya.sumber
Cara pythonic bisa jadi:
"".join([(" "+i if i.isupper() else i) for i in 'TheLongAndWindingRoad']).strip().split() ['The', 'Long', 'And', 'Winding', 'Road']
Berfungsi baik untuk Unicode, hindari re / re2.
"".join([(" "+i if i.isupper() else i) for i in 'СуперМаркетыПродажаКлиент']).strip().split() ['Супер', 'Маркеты', 'Продажа', 'Клиент']
sumber
Cara alternatif tanpa menggunakan regex atau enumerate:
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(' ')
Saya pikir ini lebih jelas dan sederhana tanpa merangkai terlalu banyak metode atau menggunakan pemahaman daftar panjang yang mungkin sulit untuk dibaca.
sumber
Cara alternatif menggunakan
enumerate
danisupper()
Kode:
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
Keluaran:
['The', 'Long', 'And', 'Winding', 'Road']
sumber
Berbagi apa yang terlintas di benak saya saat membaca postingan. Beda dari postingan lainnya.
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
sumber
Ganti setiap huruf besar 'L' yang diberikan dengan spasi kosong ditambah huruf "L". Kita dapat melakukan ini dengan menggunakan pemahaman daftar atau kita dapat mendefinisikan fungsi untuk melakukannya sebagai berikut.
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']
Jika Anda memilih menggunakan suatu fungsi, berikut caranya.
def splitAtUpperCase(text): result = "" for char in text: if char.isupper(): result += " " + char else: result += char return result.split()
Dalam kasus contoh yang diberikan:
print(splitAtUpperCase('TheLongAndWindingRoad')) >>>['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road']
Tetapi sebagian besar waktu kita memisahkan kalimat menjadi huruf besar, biasanya kita ingin mempertahankan singkatan yang biasanya merupakan aliran huruf besar yang berkelanjutan. Kode di bawah ini akan membantu.
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']
Terima kasih.
sumber