我有一个清单
In [4]: a = [1, 2, 3, 3, 2, 4]
我希望通过使用标记列表(见下文原因)通过理解删除重复项:
In [8]: [x if x not in seen else seen.append(x) for x in a]
Out[8]: [1, 2, 3, 3, 2, 4]
似乎没有考虑看到(既未更新,也未检查)。为什么会这样?
至于使用复杂方法的原因:我所拥有的列表的格式为
[{'a': 3, 'b': 4}, {'a': 10, 'b': 4}, {'a': 5, 'b': 5}]
我希望根据上面案例中特定键(b
)的值删除重复项,以便离开[{'a': 3, 'b': 4}, {'a': 5, 'b': 5}]
(我不关心删除哪个dict)。这个想法是构建一个值为b
的标记列表,并且只保留没有b
的字典等于该标记列表中的任何元素。
答案 0 :(得分:3)
由于x
不在seen
,因此您永远不会将其添加到seen
; <{1}}为真时,else
分支未执行。
但是,您正在使用条件表达式; 总是产生一个值;要么x not in seen
还是x
的结果(seen.append()
),所以你没有过滤,你在这里映射。
如果您想过滤,请在 None
循环之后将测试移至if
部分:
for
由于您使用的是seen = set()
[x for x in a if not (x in seen or seen.add(x))]
,我认为您使用的是列表;我改为使用seen.append()
,因为使用集合会员测试更快。
只有当a)set()
为真时(我们已经看过它),x
排除了,或x in seen
返回了一个真值({} {1}}不是真的)。是的,如果只是有点复杂,这是有效的。
演示:
seen.append(x)
将此问题应用于您的具体问题:
None
答案 1 :(得分:3)
您永远不会执行if的else
部分,因为第一次匹配时不会更新。你可以这样做:
[seen.append(x) or x for x in lst if x not in seen]
这样or
返回最后一个值(并使用append
执行更新(总是返回None
),让或继续寻找真值y。< / p>
也许您可以使用dict
密钥为此设置的事实。如果您想优先处理最后一项,请使用reversed
(此处的最后一项优先顺序):
>>> lst = [{'a': 3, 'b': 4}, {'a': 10, 'b': 4}, {'a': 5, 'b': 5}]
>>> filtered = {item['b']: item for item in reversed(lst)}
>>> filtered.values()
[{'a': 3, 'b': 4}, {'a': 5, 'b': 5}]
这使用'b'
作为映射值的键,因此只有一个elemnt可以映射到&#39; b'
的值,这有效地创建了一个{{1 }}
注意:这将以随机顺序返回值。为了很好地修复它,对于大数据集,我创建了另一个映射,每个对象在它的原始列表中的索引(O(n)),并使用该映射作为最终的排序函数结果(O(n * log(n)))。这超出了这个答案的范围。
答案 2 :(得分:0)
我总是在使用运算符优先级作为执行流控制。虽然它确实带来了元组创建的额外成本,但我觉得下面的内容更为明确和可口。
b_values = set()
[(item, b_values.add(item['b']))[0] for item in original_list
if item['b'] not in b_values]
但实际上当你维护/更新某种状态时,我认为最好的格式是简单的for循环:
output_list = []
b_values = set()
for item in original_list:
if item['b'] not in b_values:
output_list.append(item)
b_values.add(item['b'])