我有一个对象列表,每个对象有3个属性,我想查找我的任何对象是否有任何重叠属性,并将它们作为具有重叠属性的对象集拉出来。
让我澄清一下:
class Obj():
'''My example objects! they have 3 attributes.'''
def __init__(a, b, c):
self.a = a
self.b = b
self.c = c
>>>> obj1 = Obj(a= 1, b = 2, c = 3)
>>>> obj2 = Obj(a= 1, b = 5, c = 6)
>>>> obj3 = Obj(a= 10, b = 12, c = 3)
>>>> obj4 = Obj(a= 0, b = 0, c = 0)
>>>> obj5 = Obj(a= 100, b = 5, c = 5)
>>>> obj6 = Obj(a = -10, b = 0, c = 56)
>>>> obj7 = Obj(a = None, b = None, c = None)
# obj2 matches obj1 on attribute: "a"
# obj3 matches obj1 on attribute: "c"
# obj5 matches obj2 on attribute: "b"
# obj6 matches obj4 on attribute: "b"
# obj7 matches no one
因此我的输出应该是:
[[obj1, obj2, obj3, obj5], [obj4, obj6], [obj7]]
有没有办法用python做到这一点?我也可以搜索这样的关键词。我试过下面的解决方案。好像......哈哈。
编辑: 不得不改变几个数字以匹配我的例子。抱歉打字错误!
编辑:我目前对解决方案的尝试:
adict = defaultdict(list)
for obj in list_objects:
adict[obj.a].append(obj)
adict[obj.b].append(obj)
adict[obj.c].append(obj)
然后为长于2的列表搜索adict.values()。然后组合列表(以某种方式) 我希望有一个优雅的解决方案?
答案 0 :(得分:4)
整个问题用集合来描述,所以让我们用集合来思考它。首先将它放入英式伪码中:
Start with an empty set of equivalence sets
For each value:
Find all the equivalence sets that have any value that matches our value
Remove those equivalent sets from the result set
Union those equivalence sets together and add our new value
Add that to the result set
应该这样做,对吧?
在Python中,空集为set()
,您可以通过调用s.remove(v)
从集合中删除值,通过调用s.add(v)
向集合添加值,然后使用集合通过调用(破坏性地)s1 |= s2
或(非破坏性地)s = set.union(s1, s2, s3, …)
。 (您可以将此与*
语法一起使用:如果您有一组集或集合列表,set.union(*s)
会为您提供所有集合的联合。)
所以,唯一棘手的问题是“找到所有具有与我们的元素匹配的元素的等价集”。 “......具有与我们的价值相匹配的任何价值”是对any
的一种理解:any(matches(value, element) for element in equivalenceset)
。并且“找到所有等价集......”是一种理解:{equivalenceset for equivalenceset in equivalencesets if …}
。
显然你还需要编写matches
函数,但这很简单:x.a == y.a or x.b == y.b or x.c == y.c
。
这应该足以自己写出来。