#python #python-3.x #string
#python #python-3.x #строка
Вопрос:
Например, у меня есть строка, которая
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
"""
Например, когда первые четыре цифры строк равны 9600
, как я могу напечатать 67/60/62/69 вместе? (которая находится в каждой из четырех следующих строк n=
)
Я пробовал что-то вроде приведенного ниже, но я не думаю, что это работает так, как ожидалось
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)
Ответ №1:
Лучше всего группировать строки с одинаковыми кодами в словаре, например:
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)
Это выведет:
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']]})
Затем вы можете легко отформатировать этот словарь, например:
for k, v in d.items():
print(k, "/".join(e[2][2:] for e in v))
результат будет:
0000 60/67
9600 67/60/62/69
1920 69/62
Ответ №2:
Обычно, если у вас есть коллекция объектов, помещение объектов в класс всегда поможет вам манипулировать ими, чтобы делать то, что вы хотите.
Ниже я привел пример кода, который показывает вам очень простой способ преобразовать объекты в класс, а затем использовать класс для выполнения того, что вы хотите, чтобы он делал.
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]))))
С выводом:
0000 60/67
9600 67/60/62/69
1920 69/62
Ответ №3:
Вот мое предложение с использованием 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))
это приведет к выводу:
60/67
67/60/62/69
69/62
Для ваших нужд я бы добавил filter
вот так в конце:
filter = "9600"
for head, group in itertools.groupby(lines, header):
if head != filter:
continue
group_list = concatenate(group)
print("/".join(group_list))
который выводит:
67/60/62/69