带有条件的列表中的唯一项目

时间:2013-07-26 10:59:56

标签: python

如果我在python中有一个列表说

thing = [[20,0,1],[20,0,2],[20,1,1],[20,0],[30,1,1]]

我想要一个结果列表

thing = [[20,1,1],[20,0,2],[30,1,1]]

即如果第一个元素相同,则删除重复项并优先考虑第二个元素中的数字1。最后,第3个元素也必须是第一个元素的唯一元素。

在这个previous question中,我们解决了一个复杂的方法,对于交易,它详细说明了购买的单位。我想在那个课程中输出其他单位。如果存在与一个课程中的两个单元相关的两个事务,则它们将显示重复(或每个后续单元的时间)。

这个问题的目的是确保停止这种重复。由于该解决方案的复杂性,它产生了一系列问题。感谢迄今为止帮助过的所有人。

3 个答案:

答案 0 :(得分:2)

我不确定您是否愿意这样做,但它适用于您的示例:

[list(i) + j for i, j in dict([(tuple(x[:2]), x[2:]) for x in sorted(thing, key=lambda x:len(x))]).items()]

编辑:

这里稍微详细一点(请注意,它更适合您对问题的描述,仅按每个子列表的长度排序,可能不是最佳解决方案):

thing = [[20,0,1],[20,0,2],[20,1,1],[20,0],[30,1,1]]
dico = {}
for x in thing:
    if not tuple(x[:2]) in dico:
        dico[tuple(x[:2])] = x[2:]
        continue
    if tuple(x[:2])[1] < x[1]:
        dico[tuple(x[:2])] = x[2:]

new_thing = []
for i, j in dico.items():
    new_thing.append(list(i) + j)

答案 1 :(得分:2)

您可能想尝试使用itertools recipes中的unique_everseen功能。

作为第一步,这是一个不包括[20, 0]的解决方案:

from itertools import filterfalse

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in filterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element

thing = [[20,0,1],[20,0,2],[20,1,1],[30,1,1]]

thing.sort(key=lambda x: 0 if x[1] == 1 else 1)

print(list(unique_everseen(thing, key=lambda x: (x[0], x[2]))))

输出:

[[20, 1, 1], [30, 1, 1], [20, 0, 2]]

答案 2 :(得分:2)

thing = [[20,0,1],[20,0,2],[20,1,1],[20,0,1],[30,1,1]]

d = {}
for e in thing:
    k = (e[0], e[2])
    if k not in d or (d[k][1] != 1 and e[1] == 1):
        d[k] = list(e)

print d.values()

[[20, 0, 2], [30, 1, 1], [20, 1, 1]]

如果您不需要初始列表:

thing = [[20,0,1],[20,0,2],[20,1,1],[20,0,1],[30,1,1]]

d = {}
for e in thing:
    k = (e[0], e[2])
    if k not in d or (d[k][1] != 1 and e[1] == 1):
        d[k] = e

thing = d.values()

[[20, 0, 2], [30, 1, 1], [20, 1, 1]]

如果您想保持列表的顺序,请使用OrderedDict

from collections import OrderedDict
d = OrderedDict()