比较来自 2 个以上列表的对象
Compare objects from more than 2 lists
有没有办法比较 2 个以上列表的所有 2 项组合?
假设有一个对象:
class obj():
def __init__():
self.name = # some name
self.number = random(10)
def equals(obj):
if self.number == obj.number:
return True
else: return False
list1,list2,list3....listX
- 所有这些列表都包含 class obj
的实例
我想比较这些列表中的所有 2 项组合和 return 相同的对象。
因此,如果 list2
中有一个 obj
,其中 obj.number
属性为 5,而 list8
中的 obj
具有 obj.number
5 , 它将被 returned.
对于两个列表,比较很简单:
for obj1 in list1:
for obj2 in list2:
if obj1.equals(obj2):
print obj1,obj2
但我不知道如何对更多的对象列表进行这种比较。
你有什么建议吗?
你可能知道,对于 X 个列表,时间复杂度将上升到 O(n^X),这远非最优(在所有列表具有相同长度的情况下 =n)
现在这完全取决于您实际想要的输出。在我看来,您想查找存在于多个列表中的对象。
以更高效的方式执行此操作的一种方法是使用字典(哈希图)并遍历每个列表。根据 self.number
散列对象。
这将导致类似于:{1: [obj1], 2: [obj2, obj3], 3: [obj4], ...}
,其中键是对象的编号,值是具有这些值的对象。
通过 运行 遍历此字典并仅考虑列表大小大于或等于 2 的条目,您最终会得到相等的对象。
这里的时间复杂度等于O(n*X),也就是~O(n)
为了说明这一点,我创建了一个简短的示例,它使用了 2 个列表:
from collections import defaultdict
class Obj():
def __init__(self, value):
self.number = value
def find_equals(list1,list2):
d = defaultdict(list)
for obj1 in list1:
d[obj1.number].append(obj1)
for obj2 in list2:
d[obj2.number].append(obj2)
return [d[i] for i in d if len(d[i]) >= 2]
def test():
l1 = [Obj(1),Obj(2),Obj(3),Obj(4)]
l2 = [Obj(5),Obj(2),Obj(3),Obj(6)]
print find_equals(l1,l2)
test()
它可能可以用漂亮的 python 构造进行优化,但它展示了它背后的想法。
输出是:
[[<__main__.Obj instance at 0x103278440>, <__main__.Obj instance at 0x103278560>], [<__main__.Obj instance at 0x103278488>, <__main__.Obj instance at 0x1032785a8>]]
测试样本中使用了编号为2
和3
的对象。
一种(非常)简单的方法是获取对象列表的交集。
为此,您必须使您的对象可散列,为每个对象列表构建一个集合。
def __hash__(self):
return self.number
然后,要检查多个列表,只需取集合交集:
x = [Obj(1) Obj(3) Obj(8) Obj(10) Obj(3)]
y = [Obj(2) Obj(9) Obj(10) Obj(3)]
intersection = x & y # -> returns {Obj(3), Obj(10)}
此实现具有最坏情况的复杂性 (n - 1) * O(L)
,其中 L 是集合长度的最大值,n 是集合的数量。
所以,就复杂性而言,我认为 DJanssens 的回答更快。
但如果性能不是问题(例如,你有小列表等),我认为能够编写更优雅:
def intersect(*lists):
return set.intersection(*map(set, lists))
或 lambda 表示法中的相同内容:
intersect = lambda *lists: set.intersection(*map(set, lists))
有没有办法比较 2 个以上列表的所有 2 项组合?
假设有一个对象:
class obj():
def __init__():
self.name = # some name
self.number = random(10)
def equals(obj):
if self.number == obj.number:
return True
else: return False
list1,list2,list3....listX
- 所有这些列表都包含 class obj
我想比较这些列表中的所有 2 项组合和 return 相同的对象。
因此,如果 list2
中有一个 obj
,其中 obj.number
属性为 5,而 list8
中的 obj
具有 obj.number
5 , 它将被 returned.
对于两个列表,比较很简单:
for obj1 in list1:
for obj2 in list2:
if obj1.equals(obj2):
print obj1,obj2
但我不知道如何对更多的对象列表进行这种比较。 你有什么建议吗?
你可能知道,对于 X 个列表,时间复杂度将上升到 O(n^X),这远非最优(在所有列表具有相同长度的情况下 =n)
现在这完全取决于您实际想要的输出。在我看来,您想查找存在于多个列表中的对象。
以更高效的方式执行此操作的一种方法是使用字典(哈希图)并遍历每个列表。根据 self.number
散列对象。
这将导致类似于:{1: [obj1], 2: [obj2, obj3], 3: [obj4], ...}
,其中键是对象的编号,值是具有这些值的对象。
通过 运行 遍历此字典并仅考虑列表大小大于或等于 2 的条目,您最终会得到相等的对象。
这里的时间复杂度等于O(n*X),也就是~O(n)
为了说明这一点,我创建了一个简短的示例,它使用了 2 个列表:
from collections import defaultdict
class Obj():
def __init__(self, value):
self.number = value
def find_equals(list1,list2):
d = defaultdict(list)
for obj1 in list1:
d[obj1.number].append(obj1)
for obj2 in list2:
d[obj2.number].append(obj2)
return [d[i] for i in d if len(d[i]) >= 2]
def test():
l1 = [Obj(1),Obj(2),Obj(3),Obj(4)]
l2 = [Obj(5),Obj(2),Obj(3),Obj(6)]
print find_equals(l1,l2)
test()
它可能可以用漂亮的 python 构造进行优化,但它展示了它背后的想法。
输出是:
[[<__main__.Obj instance at 0x103278440>, <__main__.Obj instance at 0x103278560>], [<__main__.Obj instance at 0x103278488>, <__main__.Obj instance at 0x1032785a8>]]
测试样本中使用了编号为2
和3
的对象。
一种(非常)简单的方法是获取对象列表的交集。 为此,您必须使您的对象可散列,为每个对象列表构建一个集合。
def __hash__(self):
return self.number
然后,要检查多个列表,只需取集合交集:
x = [Obj(1) Obj(3) Obj(8) Obj(10) Obj(3)]
y = [Obj(2) Obj(9) Obj(10) Obj(3)]
intersection = x & y # -> returns {Obj(3), Obj(10)}
此实现具有最坏情况的复杂性 (n - 1) * O(L)
,其中 L 是集合长度的最大值,n 是集合的数量。
所以,就复杂性而言,我认为 DJanssens 的回答更快。
但如果性能不是问题(例如,你有小列表等),我认为能够编写更优雅:
def intersect(*lists):
return set.intersection(*map(set, lists))
或 lambda 表示法中的相同内容:
intersect = lambda *lists: set.intersection(*map(set, lists))