Por ejemplo, tengo una cadena que es

textstring= """
0000 Onn ch=1 n=60 v=50   
0000 Onn ch=1 n=67 v=50
9600 Off ch=1 n=67 v=00
9600 Off ch=1 n=60 v=00
9600 Onn ch=1 n=62 v=50
9600 Onn ch=1 n=69 v=50
1920 Off ch=1 n=69 v=00
1920 Off ch=1 n=62 v=00
"""   

Cuando los primeros cuatro dígitos de las líneas son iguales, por ejemplo 9600, ¿cómo puedo imprimir 67/60/62/69 juntos? (que es de cada una de las cuatro líneas después de n=)

He intentado algo como a continuación, pero no creo que funcione como se esperaba

for i, char in enumerate(textstring):
    if char=="O" and (textstring[i+1]=="f" or textstring[i+1]=="n"):
        if textstring[i-5]==textstring[i+18] and textstring[i-4]==textstring[i+19] and textstring[i-3]==textstring[i+20] and textstring[i-2]==textstring[i+21]:
            if char=="n" and textstring[i+1]=="=":  #we look for "n=" in the text
                note=int (textstring[i+2]+textstring[i+3])  #we restore the int from string after "n=", the use it as a note
                note2=int (textstring[i+25]+textstring[i+26])
                print(note)
                print(note2)
5
Kevin 13 ago. 2020 a las 03:58

3 respuestas

La mejor respuesta

Es mejor agrupar líneas con los mismos códigos en un diccionario, por ejemplo:

from collections import defaultdict
from pprint import pprint

d = defaultdict(list)
for line in textstring.splitlines():
  cells = line.split()
  if len(cells) > 1:
    line_id, *values = cells
    d[line_id].append(values)
pprint(d)

Esto dará como resultado:

defaultdict(<class 'list'>,
            {'0000': [['Onn', 'ch=1', 'n=60', 'v=50'],
                      ['Onn', 'ch=1', 'n=67', 'v=50']],
             '1920': [['Off', 'ch=1', 'n=69', 'v=00'],
                      ['Off', 'ch=1', 'n=62', 'v=00']],
             '9600': [['Off', 'ch=1', 'n=67', 'v=00'],
                      ['Off', 'ch=1', 'n=60', 'v=00'],
                      ['Onn', 'ch=1', 'n=62', 'v=50'],
                      ['Onn', 'ch=1', 'n=69', 'v=50']]})

A continuación, puede formatear fácilmente este diccionario, como:

for k, v in d.items():
  print(k, "/".join(e[2][2:] for e in v))

La salida sería:

0000 60/67
9600 67/60/62/69
1920 69/62
1
Selcuk 13 ago. 2020 a las 01:12

Aquí está mi propuesta con itertools:

import itertools

textstring = """
0000 Onn ch=1 n=60 v=50   
0000 Onn ch=1 n=67 v=50
9600 Off ch=1 n=67 v=00
9600 Off ch=1 n=60 v=00
9600 Onn ch=1 n=62 v=50
9600 Onn ch=1 n=69 v=50
1920 Off ch=1 n=69 v=00
1920 Off ch=1 n=62 v=00
"""

def header(line):
    """Return the first four digits. You can change how this is done."""
    return line.split()[0] if line else None

def concatenate(group):
    """Return the 'n=' part. Be smarter about that, this is ugly."""
    return [entry[16:18] for entry in group]

for head, group in itertools.groupby(lines, header):
    group_list = concatenate(group)
    print("/".join(group_list))

Esto producirá la salida:


60/67
67/60/62/69
69/62

Para sus necesidades, agregaría un filter como este al final:

filter = "9600"

for head, group in itertools.groupby(lines, header):
    if head != filter:
        continue
    group_list = concatenate(group)
    print("/".join(group_list))

Que salidas: 67/60/62/69

0
romaingz 14 ago. 2020 a las 09:25

Por lo general, si tiene una colección de objetos, poner los objetos en una clase siempre lo ayudará a manipularlos para hacer lo que desee.

A continuación, puse un código de ejemplo que le muestra una forma muy básica de analizar los objetos en una clase y luego usar la clase para hacer lo que quiere que haga.

textstring = """
0000 Onn ch=1 n=60 v=50   
0000 Onn ch=1 n=67 v=50
9600 Off ch=1 n=67 v=00
9600 Off ch=1 n=60 v=00
9600 Onn ch=1 n=62 v=50
9600 Onn ch=1 n=69 v=50
1920 Off ch=1 n=69 v=00
1920 Off ch=1 n=62 v=00
"""   

# You appear to have a list of objects, so lets make a class that represents the object.
# The code inside here is very basic and assumes perfect input.
class MyThing():
    def __init__(self, description: str):
        fields = description.split()
        self.Id: int = int(fields[0])
        self.State: str = fields[1]
        self.Channel: int = int(fields[2][3:])
        self.N: int = int(fields[3][2:])
        self.V: int = int(fields[4][2:])

    def __str__(self):
        # I use .format here but you can use f'' format strings in python >3.6
        return '{:0>4d} {} ch={} n={} v={}'.format(self.Id, self.State, self.Channel, self.N, self.V)

if __name__ == '__main__':
    objects = (MyThing(desc) for desc in textstring.splitlines() if desc != '')

    # create a grouping so you can manipulate objects by matching id's
    grouping = defaultdict(list)
    for thing in objects:
        grouping[thing.Id].append(thing)

    for key in grouping.keys():
        # print out the items that match the group
        print('{:0>4d} {}'.format(key, '/'.join((str(thing.N) for thing in grouping[key]))))

Con la salida:

0000 60/67
9600 67/60/62/69
1920 69/62
1
Serdalis 13 ago. 2020 a las 01:34