separar palabra minusculas mayusculas mayus letras entre distingue contar contador comparar cadenas python regex string

minusculas - separar palabra en letras python



Dividir una cadena en letras mayúsculas (12)

¿Cuál es la forma pitónica de dividir una cadena antes de las apariciones de un conjunto dado de caracteres?

Por ejemplo, quiero dividir ''TheLongAndWindingRoad'' en cualquier aparición de una letra mayúscula (posiblemente excepto la primera), y obtener [''The'', ''Long'', ''And'', ''Winding'', ''Road''] .

Edición: También debería dividir las ocurrencias individuales, es decir, de ''ABC'' Me gustaría obtener [''A'', ''B'', ''C''] .


Aquí hay una solución regex alternativa. El problema se puede volver a escribir como "¿Cómo inserto un espacio antes de cada letra en mayúscula, antes de hacer la división":

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

Esto tiene la ventaja de preservar todos los caracteres que no son espacios en blanco, que la mayoría de las otras soluciones no lo hacen.


Desafortunadamente, no es posible dividir en una coincidencia de ancho cero en Python. Pero puedes usar re.findall en re.findall lugar:

>>> import re >>> re.findall(''[A-Z][^A-Z]*'', ''TheLongAndWindingRoad'') [''The'', ''Long'', ''And'', ''Winding'', ''Road''] >>> re.findall(''[A-Z][^A-Z]*'', ''ABC'') [''A'', ''B'', ''C'']


Esto es posible con la herramienta more_itertools.split_before .

import more_itertools as mit iterable = "TheLongAndWindingRoad" [ "".join(i) for i in mit.split_before(iterable, lambda s: s.isupper())] # [''The'', ''Long'', ''And'', ''Winding'', ''Road'']

También debería dividir las ocurrencias individuales, es decir, de ''ABC'' me gustaría obtener [''A'', ''B'', ''C''] .

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

more_itertools es un paquete de terceros con más de 60 herramientas útiles que incluyen implementaciones para todas las recetas originales de itertools , lo que evita su implementación manual.


Otro sin expresiones regulares y la capacidad de mantener mayúsculas contiguas si se desea

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


Reemplace cada letra mayúscula ''L'' en el dado con un espacio vacío más esa letra "L".

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

En el caso del ejemplo dado:

print(splitAtUpperCase(''TheLongAndWindingRoad'')) [''The'', ''Long'', ''And'', ''Winding'', ''Road'']

También podría usar un bucle for con una sentencia if como

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 '' ''.join(s.split) print(splitAtUpperCase(TheLongAndWindingRoad) >>>> ''The Long And Winding Road''

Gracias.


Solución alternativa (si no te gustan las expresiones regulares explícitas):

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


Una forma alternativa sin usar expresiones regulares o enumerar:

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

Creo que es más claro y sencillo sin encadenar demasiados métodos o usar una larga lista de comprensión que puede ser difícil de leer.


Una forma alternativa utilizando enumerate y isupper()

Código:

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

Salida:

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


Una variación de la solución de @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"))

o

[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)


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

Si desea que "It''sATest" divida a ["It''s", ''A'', ''Test''] cambie el rexeg a "[AZ][a-z'']*"