【问题标题】:Python find and replace last appearance in listPython查找并替换列表中的最后一次出现
【发布时间】:2016-09-08 01:06:16
【问题描述】:

在 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')]

【问题讨论】:

  • 输入列表总是排序的吗?
  • 是的,它已经作为示例排序了
  • 另外,你能把方括号放在它们所属的地方吗?我只是想确保我将其作为元组列表正确阅读。
  • 元组是不可变的,因此您可能希望首先将其转换为列表。
  • 我更新了问题。请帮我找出解决方案

标签: python list


【解决方案1】:

反向处理您的输入列表,然后标记任何值的第一次。您可以使用一组列表来跟踪您已经看到的值。完成后反转您构建的输出列表:

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')]

【讨论】:

  • 无论如何,只要您使用list,也许将最后一行从outputlist = outputlist[::-1] 更改为outputlist.reverse() 以执行就地反转而不是创建一个新的反转list 和扔掉旧的?
  • 我觉得我的更短:)
  • @MadPhysicist:您的将所有值视为一个命名空间;我每列使用一组。
  • @MadPhysicist:您还为每个唯一值使用list.index(),这相当昂贵。
  • 从 OP 的帖子中不清楚命名空间是否是独立的。
【解决方案2】:

如果您不是在这里寻找闪电般的速度,您可以执行以下操作:

  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')]

【讨论】:

    【解决方案3】:

    另一种收集方法会不断添加索引,以便您最终获得最后一次出现的索引,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()
    

    【讨论】:

      猜你喜欢
      • 2016-03-30
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多