【问题标题】:Get new unique list containg only last occuring elements from original list获取新的唯一列表仅包含原始列表中最后出现的元素
【发布时间】:2016-03-01 16:50:14
【问题描述】:

对不起,我真的不知道如何命名我的问题。我正在寻找“最 Pythonic”的方法来解决以下问题:

AA = [["a", 1], ["b", 1], ["c", 1], ["a", 3], ["b", 5], ["a", 7]]
BB = []
for elem in AA:
    if elem[0] not in [elemb[0] for elemb in BB]:
        BB.append(elem)
    else:
        BB[
            [belem[0] for belem in BB].index(elem[0])
        ] = elem
for elem in BB:
    print(elem)

即:我有一个列表列表,每个列表包含两个元素,现在我想把它变成一个新列表,原始列表的列表元素的每个第一个值只出现一次。

上面的代码解决了这个任务,也就是转

[["a", 1], ["b", 1], ["c", 1], ["a", 3], ["b", 5], ["a", 7]]

进入

[["a", 7], ["b", 5], ["c", 1]]

正如我所愿,但它不是很优雅,我怀疑它是否是最好的解决方案。

通过使用字典,我想到了一个想法。简短的版本是:

CC = {elem[0] : elem[1] for elem in AA}
BB = [[elem, CC[elem]] for elem in CC]
BB.sort()
for elem in BB:
    print(elem)

还有更长的(我需要它有几个原因):

CC = {}
for elem in AA:
    try:
        oldelem = CC[elem[0]]
        CC[elem[0]] = elem[1]
        print("Element '{:}' replaced: {:d} -> {:d}".format(
            elem[0], oldelem, elem[1]
        ))
    except KeyError:
        CC[elem[0]] = elem[1]
BB = [[elem, CC[elem]] for elem in CC]
BB.sort()
for elem in BB:
    print(elem)

dict 的问题在于,如果列表元素变得更复杂,它可能会变得有限制,并且对于替换会有一些额外的限制(即某些值大于/小于要替换的元素的值等.)

所以现在我的问题是:是否有一种简短/“更好”/更清洁的方式来完成这项任务?

【问题讨论】:

  • 你的预期输出是什么?
  • 我不太确定你想要什么新列表,你能说得更具体点吗?
  • 因为它看起来有点滥用列表理解......就是这样。
  • 如果您的 dict 解决方案太有限,请告诉我们它的不足之处。如果我们不了解您的要求,就很难提出替代方案。
  • @das-g:我认为 dict 会变得有限制,如果我有类似A = [["a", 1, True, .123], ["b", 5, False .123], ["a", 7, True, .537] ] 的东西,并且想要替换第一个元素相等,而第四个元素相等并且以此类推。

标签: python list dictionary replace set


【解决方案1】:

您可以使用OrderedDict 来保留每对的最后一次出现:

>>> from collections import OrderedDict
>>> d=OrderedDict({i:j for i,j in AA})

>>> d.items()
[('a', 7), ('c', 1), ('b', 5)]

【讨论】:

    【解决方案2】:

    由于新的 key:value 分配给字典会自动覆盖旧的,答案就像dict() 一样简单:

    >>> AA = [["a", 1], ["b", 1], ["c", 1], ["a", 3], ["b", 5], ["a", 7]]
    >>> dict(AA)
    {'a': 7, 'b': 5, 'c': 1}
    

    【讨论】:

    • 高效且仅内置插件。
    【解决方案3】:

    比 Kasramvd 的回答略有改进:

    >>> from collections import OrderedDict
    >>> print OrderedDict(AA).items()
    [('a', 7), ('b', 5), ('c', 1)]
    

    或者如果你不关心效率(或者如果 AA 很短):

    >>> print sorted(dict(AA).items())
    [('a', 7), ('b', 5), ('c', 1)]
    

    【讨论】:

      【解决方案4】:

      AA 的结构已经适合用作dictcollections.OrderedDict 的初始化参数,所以你可以这样做:

      from collections import OrderedDict
      BB = OrderedDict(AA).items()
      

      【讨论】:

        【解决方案5】:

        来自cmets:

        我认为 dict 会变得有限制,如果我有一些东西的话 比如 A = [["a", 1, True, .123], ["b", 5, False .123], ["a", 7, True, .537] ],并且想要替换第一个元素 相等,第 4 个元素相等,以此类推。

        @TigerhawkT3 的出色解决方案可以轻松扩展以满足该(附加的、新的)需求:

        import sys
        
        items = None
        if sys.version_info[0] == 3:
            items = lambda d: d.items()
        else:    
            items = lambda d: d.iteritems()
        
        AAA = [["a", 1, True, .123], ["b", 5, False, .123], ["a", 7, True, .537]]
        
        def last_unique(arr, key_pos):
            return list(v for k,v in items(dict([aa[key_pos],aa] for aa in arr)))
        
        for key_pos in range(0,4):
            print(last_unique(AAA, key_pos))
        

        输出:

        [['a', 7, True, 0.537], ['b', 5, False, 0.123]]
        [['a', 1, True, 0.123], ['b', 5, False, 0.123], ['a', 7, True, 0.537]]
        [['b', 5, False, 0.123], ['a', 7, True, 0.537]]
        [['b', 5, False, 0.123], ['a', 7, True, 0.537]]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多