很像filter
工作,我希望能够从序列中删除重复的项目,但是根据回调的返回值。
set
不允许这样做。
my_list = [{'foo': 330}, {'foo': 560}, {'foo': 320}]
# What I would like:
remove_duplicate(my_list, lambda val: int(val['foo']/100))
# Would return
[{'foo': 330}, {'foo': 560}]
# or
[{'foo': 560}, {'foo': 320}]
我实际上并不关心订单或要保留的订单,我认为所有这些数据都是重复的。
理想情况下,我正在寻找一种内置的方法来实现这一目标。
答案 0 :(得分:2)
嗯,事实证明没有内置方法可以做到这一点。
但是有一个很好的黑客:
通过使用dict
永远不会有两倍相同密钥的事实,您可以这样做:
list({callback(val): val for val in my_list}.values())
# In your case:
list({int(val['foo']/100): val for val in my_list}.values())
# Returns:
[{'foo': 320}, {'foo': 560}]
如果您关心订单,文档会提出以下方法unique_everseen
:
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 ifilterfalse(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
哪个更优雅,但遗憾的是(IMO),不是内置的。
答案 1 :(得分:1)
您可以实际使用过滤功能。不幸的是,没有lambda表达式,因为它们不支持赋值。相反,您可以定义一个函数来检查val [' foo'] / 100是否已经在您已经看过的项目集中。如果没有,请保留它。否则,不要。
my_list = [{'foo': 330}, {'foo': 560}, {'foo': 320}]
kept_set = set()
def cut_fun(x):
remove_ind = int( x['foo']/100)
if remove_ind in kept_set:
return 0
kept_set.add(remove_ind)
return 1
print filter(cut_fun, my_list)