简体   繁体   English

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

[英]Unique items in a list with condition

If i have a list in python say 如果我在python中有一个列表说

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

I would want to have a resulting list 我想要一个结果列表

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

That is if the first element is the same, remove duplicates and give priority to the number 1 in the second element. 也就是说,如果第一个元素相同,则删除重复项并优先考虑第二个元素中的数字1。 Lastly the 3rd element must also be unique to the first element. 最后,第三个元素也必须是第一个元素的唯一元素。

In this previous question we solved a complicated method where for a transaction it details a purchased unit. 上一个问题中,我们解决了一个复杂的方法,对于交易,它详细说明了购买的单位。 I want to output other units in that course. 我想在那个课程中输出其他单位。 If two transactions exist that relate to two units in one course it will display them a duplicate (or times each subsequent unit). 如果存在与一个课程中的两个单元相关的两个事务,则它们将显示重复(或每个后续单元的时间)。

The aim of this question it to ensure that this duplication is stopped. 这个问题的目的是确保这种重复停止。 Because of the complication of this solution it has resulted in a series of question. 由于该解决方案的复杂性,它产生了一系列问题。 Thanks for everyone that has helped so far. 感谢迄今为止帮助过的所有人。

I am not sure you would like this, but it works with your example: 我不确定你会喜欢这个,但它适用于你的例子:

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

EDIT: 编辑:

Here a bit more detailed (note that it fits better to your description of the problem, sorting ONLY by the length of each sublist, may not be the best solution): 这里更详细一些(请注意,它更适合您对问题的描述,仅按每个子列表的长度排序,可能不是最佳解决方案):

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)

You might want to try using the unique_everseen function from the itertools recipes . 您可能想尝试使用itertools配方中unique_everseen函数。

As a first step, here is a solution excluding [20, 0] : 作为第一步,这是一个不包括[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]))))

Output: 输出:

[[20, 1, 1], [30, 1, 1], [20, 0, 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]]

if you don't need initial list: 如果你不需要初始清单:

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

if you want to keep order of your lists, use OrderedDict 如果您想保持列表的顺序,请使用OrderedDict

from collections import OrderedDict
d = OrderedDict()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM