Python находит и заменяет последнее появление в списке

В Python у меня есть список списков

list3 = ['PA0', 'PA1'] list2 = ['PB0', 'PB1'] list1 = ['PC0', 'PC1', 'PC2'] [(list1[i], list2[j], list3[k]) for i in xrange(len(list1)) for j in xrange(len(list2)) for k in xrange(len(list3))] #Result [('PC0', 'PB0', 'PA0'), ('PC0', 'PB0', 'PA1'), ('PC0', 'PB1', 'PA0'), ('PC0', 'PB1', 'PA1'), ('PC1', 'PB0', 'PA0'), ('PC1', 'PB0', 'PA1'), ('PC1', 'PB1', 'PA0'), ('PC1', 'PB1', 'PA1'), ('PC2', 'PB0', 'PA0'), ('PC2', 'PB0', 'PA1'), ('PC2', 'PB1', 'PA0'), ('PC2', 'PB1', 'PA1')] 

Как я могу найти последнее появление и добавить E в качестве суффикса

 [('PC0', 'PB0', 'PA0'), 
  ('PC0', 'PB0', 'PA1'), 
  («PC0», «PB1», «PA0»), 
  ( «PC0E» , «PB1», «PA1»), 
  ('PC1', 'PB0', 'PA0'), 
  («PC1», «PB0», «PA1»), 
  («PC1», «PB1», «PA0»), 
  ( «PC1E» , «PB1», «PA1»), 
  («PC2», «PB0», «PA0»), 
  («PC2», «PB0E» , «PA1»), 
  («PC2», «PB1», «PA0E» ), 
  ( «PC2E» , «PB1E» , «PA1E» )]

Обработайте список входных данных в обратном порядке, а затем отметьте первое вхождение любого значения. Вы можете использовать список наборов для отслеживания значений, которые вы уже видели. Обратный вывод списка вы создаете, когда вы закончите:

 seensets = [set() for _ in inputlist[0]] outputlist = [] for entry in reversed(inputlist): newentry = [] for value, seen in zip(entry, seensets): newentry.append(value + 'E' if value not in seen else value) seen.add(value) outputlist.append(tuple(newentry)) outputlist.reverse() 

Демо-версия:

 >>> seensets = [set() for _ in inputlist[0]] >>> outputlist = [] >>> for entry in reversed(inputlist): ... newentry = [] ... for value, seen in zip(entry, seensets): ... newentry.append(value + 'E' if value not in seen else value) ... seen.add(value) ... outputlist.append(tuple(newentry)) ... >>> outputlist.reverse() >>> pprint(outputlist) [('PC0', 'PB0', 'PA0'), ('PC0', 'PB0', 'PA1'), ('PC0', 'PB1', 'PA0'), ('PC0E', 'PB1', 'PA1'), ('PC1', 'PB0', 'PA0'), ('PC1', 'PB0', 'PA1'), ('PC1', 'PB1', 'PA0'), ('PC1E', 'PB1', 'PA1'), ('PC2', 'PB0', 'PA0'), ('PC2', 'PB0E', 'PA1'), ('PC2', 'PB1', 'PA0E'), ('PC2E', 'PB1E', 'PA1E')] 

Если вы не ищете молниеносную скорость здесь, вы можете сделать следующее:

  1. Сгладить список, используя https://stackoverflow.com/a/952952/2988730
  2. Найдите уникальные элементы
  3. Найдите индекс последнего вхождения каждого уникального элемента (путем изменения списка)
  4. Обновить элемент
  5. Выполните форматирование сплющенного списка с помощью https://stackoverflow.com/a/10124783/2988730

Вот пример реализации:

 # 1 flat = list(reversed([x for group in mylist for x in group])) # 2 uniq = set(flat) # 3, 4 for x in uniq: flat[flat.index(x)] += 'E' # 5 mylist = list(zip(*[reversed(flat)]*3)) 

Результат:

 [('PC0', 'PB0', 'PA0'), ('PC0', 'PB0', 'PA1'), ('PC0', 'PB1', 'PA0'), ('PC0E', 'PB1', 'PA1'), ('PC1', 'PB0', 'PA0'), ('PC1', 'PB0', 'PA1'), ('PC1', 'PB1', 'PA0'), ('PC1E', 'PB1', 'PA1'), ('PC2', 'PB0', 'PA0'), ('PC2', 'PB0E', 'PA1'), ('PC2', 'PB1', 'PA0E'), ('PC2E', 'PB1E', 'PA1E')] 

Другой подход, который собирает, добавляет индексы, поэтому вы получаете индексы для последнего вхождения, itertools.product также создаст для вас начальный список:

 from itertools import product def last_inds(prod): # the key/value will be overwritten so we always keep the last seen return {ele: (i1, i2) for i1, prod in enumerate(prod) for i2, ele in enumerate(prod)} prod = list(product(*(list1, list2, list3))) # use the indexes to change the last occurrences. for r, c in last_inds(prod).values(): lst = list(prod[r]) lst[c] += "E" prod[r] = tuple(lst) 

Что дает ожидаемый результат:

 [('PC0', 'PB0', 'PA0'), ('PC0', 'PB0', 'PA1'), ('PC0', 'PB1', 'PA0'), ('PC0E', 'PB1', 'PA1'), ('PC1', 'PB0', 'PA0'), ('PC1', 'PB0', 'PA1'), ('PC1', 'PB1', 'PA0'), ('PC1E', 'PB1', 'PA1'), ('PC2', 'PB0', 'PA0'), ('PC2', 'PB0E', 'PA1'), ('PC2', 'PB1', 'PA0E'), ('PC2E', 'PB1E', 'PA1E')] 

В моих таймингах это самый быстрый подход с использованием ваших данных.

 In [37]: %%timeit prod = list(product(*(list1, list2, list3))) m(prod) ....: 10000 loops, best of 3: 20.7 µs per loop In [38]: %%timeit prod = list(product(*(list1, list2, list3))) for r, c in last_inds(prod).values(): lst = list(prod[r]) lst[c] += "E" prod[r] = tuple(lst) ....: 100000 loops, best of 3: 12.2 µs per loop 

Где m:

 def m(inputlist): seensets = [set() for _ in inputlist[0]] outputlist = [] for entry in reversed(inputlist): newentry = [] for value, seen in zip(entry, seensets): newentry.append(value + 'E' if value not in seen else value) seen.add(value) outputlist.append(tuple(newentry)) outputlist.reverse()