首页 > 解决方案 > 在Python中查找具有相同属性的列表中的两个元素

问题描述

我想在列表中找到具有相同属性的任何一对元素。例如,

class X:
    def __init__(self, param):
        self.param = param

my_list = [X(1), X(2), X(3), X(2), X(3), X(3)]

因此,如果比较 on x.param,我会寻找my_list[1], my_list[3]ormy_list[2], my_list[4]my_list[2], my_list[5]or my_list[4], my_list[5]。但是,不能保证列表必须包含具有相同属性的任何元素,例如

my_list = [X(1), X(2), X(3)]

也可能是此函数的有效参数。

这样做的明显方法似乎是:

def find_dupe(my_list, my_lambda):
    attrs = dict()
    for item in my_list:
        if my_lambda(item) in attrs:
             return [attrs[my_lambda(item)], item]
        attrs[my_lambda(item)] = item
    return []

但这似乎有点不雅,我想知道是否有更好的方法来做到这一点。

标签: pythonlistoopdictionaryattributes

解决方案


collections.defaultdict提供按属性对对象分组的 O(n) 解决方案:

from collections import defaultdict

class X:
    def __init__(self, param):
        self.param = param

my_list = [X(1), X(2), X(3), X(2), X(3), X(3)]

d = defaultdict(list)

for i in my_list:
    d[i.param].append(i)

结果表明一个对象带有param == 1,两个对象带有param == 2,三个对象带有param == 3

print(d)

defaultdict(list,
            {1: [<__main__.X at 0x855eb70>],
             2: [<__main__.X at 0x855e588>, <__main__.X at 0x856ae48>],
             3: [<__main__.X at 0x856af60>, <__main__.X at 0x856ad68>, <__main__.X at 0x856acf8>]})

要提取具有相同属性的对象,只需过滤字典中长度大于 1 的值的项目。然后使用itertools.combinations提取这些键的所有组合。


推荐阅读