Tengo una cadena multilínea en Python que se ve así

"""1234 dog list some words 1432 cat line 2 1789 cat line3 1348 dog line 4 1678 dog line 5 1733 fish line 6 1093 cat more words"""

Quiero poder agrupar líneas específicas por los animales en python. Entonces mi salida se vería así

dog
1234 dog list some words 
1348 dog line 4
1678 dog line 5

cat
1432 cat line 2 
1789 cat line3 
1093 cat more words

fish
1733 fish line 6

Hasta ahora sé que necesito dividir el texto por cada línea

def parser(txt):
    for line in txt.splitlines():
        print(line)

Pero no estoy seguro de cómo continuar. ¿Cómo agruparía cada línea con un animal?

0
stillearning 3 oct. 2019 a las 22:43

3 respuestas

La mejor respuesta

Puede utilizar defaultdict y dividir cada línea:

from collections import defaultdict

txt = """123 dog foo
456 cat bar
1234 dog list some words
1348 dog line 4
1432 cat line 2 
1789 cat line3 
1093 cat more words
1678 dog line 5
"""


def parser(txt):
    result = defaultdict(list)
    for line in txt.splitlines():
        num, animal, _ = line.split(' ', 2)  # split the first 2 blancs, skip the rest!
        result[animal].append(line)  # add animal and the whole line into result
    return result

result = parser(txt)
for animal, lines in result.items():
    print('>>> %s' % animal)
    for line in lines:
        print(line)
    print("")

Salida:

>>> dog
123 dog foo
1234 dog list some words
1348 dog line 4
1678 dog line 5

>>> cat
456 cat bar
1432 cat line 2 
1789 cat line3 
1093 cat more words
1
Maurice Meyer 3 oct. 2019 a las 20:18
str1 = """1234 dog list some words 1432 cat line 2 1789 cat line3 1348 dog line 4 1678 dog line 5 1733 fish line 6 1093 cat more words"""

animals = ["dog", "cat", "fish"]
tmp = {}
tmp1= []
currentAnimal = ""
listOfWords = str1.split(" ")
for index, line in enumerate(listOfWords, start=1):
    if line in animals:
        currentAnimal = line
        if len(tmp1)>0:
            tmp1.pop()
            if currentAnimal not in tmp.keys():
                tmp[currentAnimal] = []
            tmp[currentAnimal].append(tmp1)
            tmp1=[]
        tmp1 = []
        tmp1.append(listOfWords[index-2])
        tmp1.append(listOfWords[index-1])
    else:
        tmp1.append(listOfWords[index-1])

for eachKey in tmp:
    print eachKey
    listOfStrings = tmp[eachKey]
    for eachItem in listOfStrings:
        if len(eachItem) > 0:
            print (" ").join(eachItem)

Salida:

fish
1678 dog line 5
dog
1789 cat line3
1348 dog line 4
cat
1234 dog list some words
1432 cat line 2
1733 fish line 6
1
Anilkumar Battaram 3 oct. 2019 a las 21:37

Sé que hay otras respuestas, pero me gusta más la mía (jajaja).

De todos modos, analicé la cadena original como si la cadena no tuviera caracteres \n (nueva línea).

Para obtener los animales y las oraciones, utilicé expresiones regulares:

import re

# original string with no new line characters
txt = """1234 dog list some words 1432 cat line 2 1789 cat line3 1348 dog line 4 1678 dog line 5 1733 fish line 6 1093 cat more words"""

# use findall to capture the groups
groups = re.findall("(?=(\d{4} (\w+) .*?(?=\d{4}|$)))", txt)

En este punto, obtengo una lista de tuplas en groups:

>>> groups
[('1234 dog list some words ', 'dog'),
 ('1432 cat line 2 ', 'cat'),
 ('1789 cat line3 ', 'cat'),
 ('1348 dog line 4 ', 'dog'),
 ('1678 dog line 5 ', 'dog'),
 ('1733 fish line 6 ', 'fish'),
 ('1093 cat more words', 'cat')]

Luego me gustaría agrupar todas las oraciones que se refieren al mismo animal. Es por eso que creé una estructura de datos llamada tabla hash (también conocido como diccionario, en Python):

# create a dictionary to store the formatted data
dct = {}
for group in groups:
    if group[1] in dct:
        dct[group[1]].append(group[0])
    else:
        dct[group[1]] = [group[0]]

El diccionario dct tiene este aspecto:

>>> dct
{'dog': ['1234 dog list some words ', '1348 dog line 4 ', '1678 dog line 5 '],
 'cat': ['1432 cat line 2 ', '1789 cat line3 ', '1093 cat more words'],
 'fish': ['1733 fish line 6 ']}

Finalmente, solo tenemos que imprimirlo en el formato que desee:

# then print the result in the format you like
for key, value in dct.items():
    print(key)
    for sentence in value:
        print(sentence)
    print()

Y la salida es:

dog
1234 dog list some words 
1348 dog line 4 
1678 dog line 5 

cat
1432 cat line 2 
1789 cat line3 
1093 cat more words

fish
1733 fish line 6 

El código final es el siguiente:

import re

# original string with no new line characters
txt = """1234 dog list some words 1432 cat line 2 1789 cat line3 1348 dog line 4 1678 dog line 5 1733 fish line 6 1093 cat more words"""

# use findall to capture the groups
groups = re.findall("(?=(\d{4} (\w+) .*?(?=\d{4}|$)))", txt)

# create a dictionary to store the formatted data
dct = {}
for group in groups:
    if group[1] in dct:
        dct[group[1]].append(group[0])
    else:
        dct[group[1]] = [group[0]]

# then print the result in the format you like
for key, value in dct.items():
    print(key)
    for sentence in value:
        print(sentence)
    print()
1
brunoluvizotto 4 oct. 2019 a las 11:46
58225904