基于元组的第一个条目,从列表中删除重复的元组

6

我有一个类似这样的元组列表:

test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]

我希望从列表中删除那些第一个元素已经出现过的元组。因此,期望的输出结果是:
[('ent1', 24), ('ent2',12), ('ent3',4.5)]

我不知道如何做到这一点。通常,如果我想删除完全重复的元组,我会使用

list(set(test))

但是在这种情况下,这并不起作用。有没有人有适当的方法来解决这个问题?
3个回答

9
你觉得 dict(test) 的输出怎么样?
{'ent1': 4, 'ent2': 3.5, 'ent3': 4.5}

或者您可能想将其转换回元组列表,方法如下:

>>> list(dict(test).items())
[('ent1', 4), ('ent2', 3.5), ('ent3', 4.5)]

编辑:这将保留最后一个分配的值,但您也可以通过首先反转列表来保留第一个分配的值:

>>> list(dict(reversed(test)).items())
[('ent2', 12), ('ent1', 24), ('ent3', 4.5)]

编辑2:如果您还想保留列表顺序,那么以下是一个好的一行解决方案(受Julien答案启发):
>>> [(uk,next(v for k,v in test if k == uk)) for uk in dict(test).keys()]
[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]

最后,使用 functools.reduce 可以得到另一个一行代码的解决方案:
>>> from functools import reduce
>>> reduce(lambda lu,i:i[0] in dict(lu).keys() and lu or lu+[i], test, [])
[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]

解释: lu是只包含唯一键的列表,itest列表中的下一个项。如果i[0],即下一个元素的键已经存在于lu中,我们保留lu,否则我们将i添加到lu中。


2
字典不保持顺序。这就是为什么我接受了另一个答案的原因。 - WinterMensch
@WinterMensch 我已相应地更新了我的答案。 - tif
1
@WinterMensch 在 Python 3.6 及之后的版本中,dict 确实 保持顺序。然而,set 仍然不保持顺序,所以你在问题中的代码不会保留顺序。 - PM 2Ring
@WinterMensch 我想现在我找到了一个优雅而好的一行代码解决方案。 - tif

2

使用检查标志

例子:

test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]
check_val = set()      #Check Flag
res = []
for i in test:
    if i[0] not in check_val:
        res.append(i)
        check_val.add(i[0])
print(res) 

输出:

[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]

1
test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]
deduplicated_test = [(s,[t[1] for t in test if t[0] == s][0]) for s in sorted(set([t[0] for t in test]))]

很抱歉,这段内容读起来很短并且令人不舒服。我不记得为什么sorted(set())有效而set()无效了,但是无论如何...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接