使用自定义相等运算符使列表唯一的最 Pythonic 方法是什么?
例如,您有一个 dicts 列表L
,并且您想要一个新列表M
,这样对于所有 dicts d
,e
inM
和一个特定的x
d[x] != e[x]
如何才能做到这一点?
使用自定义相等运算符使列表唯一的最 Pythonic 方法是什么?
例如,您有一个 dicts 列表L
,并且您想要一个新列表M
,这样对于所有 dicts d
,e
inM
和一个特定的x
d[x] != e[x]
如何才能做到这一点?
在您的情况下(以及等价归结为某种键的等价的所有情况),您可以简单地构造一个字典,其中的键是您要比较的值:
L = [{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}, {'key': 'foo', 'v': 44}]
x = 'key'
M = {d[x]:d for d in L}.values()
# In old Python versions: dict((d[x],d for d in L)).values()
请注意,结果不是确定性的,两者
[{'key': 'foo', 'v': 44}, {'key': 'bar', 'v': 43}]
和
[{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}]
是有效的结果。
在一般情况下,只需检查所有接受的值:
def unique(iterable, is_eq):
tmp = []
for el in iterable:
if not any(is_eq(inTmp, el) for inTmp in tmp):
tmp.append(is_eq)
return tmp
请注意,这意味着您的比较函数将被称为O(n²)
时间而不是n
时间。
基于 FUD 对 phihag 的评论。请注意,key
函数必须返回一个可散列值。
def unique(iterable, key=lambda x : x):
seen = set()
res = []
for item in iterable:
k = key(item)
if k not in seen:
res.append(item)
seen.add(k)
return res
from operator import itemgetter
L = [{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}, {'key': 'foo', 'v': 44}]
print unique(L, key=itemgetter('key'))
#[{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}]
我不确定这种事情是否承认单线,但在我看来,set
课程是你想要什么的关键。
M = []
uniques = set(d[x] for d in L)
for d in L:
if d[x] in uniques:
uniques.remove(d[x])
M.append(d)
注意:phihag 的答案似乎更像 Pythonic,但这可能会更自我记录
使用字典理解:
def unique(itrable,key):
return {key(x):x for x in itrable}.values()
>>> unique('abcdbbcdab', lambda x: x)
['a', 'c', 'b', 'd']
>>> unique([10, -20, 20, 30], lambda x: abs(x))
[10, 20, 30]