根据回调删除重复项

时间:2016-02-12 15:51:13

标签: python callback duplicates

很像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}]

我实际上并不关心订单或要保留的订单,我认为所有这些数据都是重复的。

理想情况下,我正在寻找一种内置的方法来实现这一目标。

2 个答案:

答案 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)