Я пытаюсь создать новый список из другого списка на основе условия:
lst = [("Id01","Code1",1),("Id01","#instr1",1),("Id01","#instr2",1),("Id01","#instr4",1),
("Id01","Code2",1),("Id01","#instr3",1),("Id01","#instr2",1),("Id02","Code2",1),
("Id02","#instr2",1),("Id02","#instr5",1)]
table, instrlist = '', ''; code, instructions = [], []; qty = 0
for idx, l in enumerate(lst):
table = l[0]
if not l[1].startswith('#'):
code = l[1]; qty = l[2]; instructions = []
else:
instructions.append(l[1])
print idx, table, code, instructions, qty
Каждый раз, когда код присутствует в кортежах после кортежа, содержащего '#', мне нужно передать правильную строку в другую часть программы и выполнить сброс, чтобы начать обработку другой. Я поставил ряд условий и получил такой результат:
0 Id01 Code1 [] 1
1 Id01 Code1 ['#instr1'] 1
2 Id01 Code1 ['#instr1', '#instr2'] 1
3 Id01 Code1 ['#instr1', '#instr2', '#instr4'] 1
4 Id01 Code2 [] 1
5 Id01 Code2 ['#instr3'] 1
6 Id01 Code2 ['#instr3', '#instr2'] 1
7 Id02 Code2 [] 1
8 Id02 Code2 ['#instr2'] 1
9 Id02 Code2 ['#instr2', '#instr5'] 1
Однако результат, который мне действительно нужен,
3 Id01 Code1 ['#instr1', '#instr2', '#instr4'] 1
6 Id01 Code2 ['#instr3', '#instr2'] 1
9 Id02 Code2 ['#instr2', '#instr5'] 1
Из какого состояния мне нужно снова фильтровать?
Я недостаточно опытен, чтобы использовать списки или встроенный фильтр, и я хотел бы оставить код максимально читабельным (для новичка), по крайней мере, до тех пор, пока я не узнаю больше.
UPDATE
Решение, предлагаемое jpp , представляется наиболее эффективным и читабельным:
from collections import defaultdict
from itertools import count, chain
lst = [("Id01","Code1",1),("Id01","#instr1",1),("Id01","#instr2",1),("Id01","#instr4",1),
("Id01","Code2",1),("Id01","#instr3",1),("Id01","#instr2",1),("Id02","Code2",1),
("Id02","#instr2",1),("Id02","#instr5",1)]
d = defaultdict(list)
enums = []
c = count()
for ids, action, num in lst:
if not action.startswith('#'):
my_ids, my_action = ids, action
enums.append(next(c))
else:
d[(my_ids, my_action)].append([action, num])
next(c)
enums = enums[1:] + [len(lst)]
for idx, ((key1, key2), val) in enumerate(d.items()):
print (enums[idx]-1, key1, key2, list(chain.from_iterable(val)), val[0][-1])
Однако я столкнулся с некоторыми проблемами.
По некоторым причинам порядок неправильный (последняя строка стала первой):
Результат:
(3, 'Id02', 'Code2', ['# instr2', 1, '# instr5', 1], 1) <--- должен быть последним </p>
(6, 'Id01', 'Code1', ['# instr1', 1, '# instr2', 1, '# instr4', 1], 1)
(9, 'Id01', 'Code2', ['# instr3', 1, '# instr2', 1], 1)
Числовое поле в кортеже не всегда равно 1, и иногда скрипт не учитывает его (отсутствует информация на моей стороне), потому что оно всегда принимает число, найденное в кортеже. Должен быть связан с кортежем Code и может быть опущен.
Я работаю над этим и обновлю свой пост, как только решу проблемы.