下面的解决方案可能对大型列表表现更好,但由于排序步骤,可能需要更多的内存。可以通过定义sortKey(例如'count')或使用字典的哈希值来执行交集,如
https://dev59.com/x2025IYBdhLWcg3wpXoe#60765557所建议的。该算法对两个列表进行排序,并并行迭代检查两个迭代器的三种可能状态:
- 第一个迭代器在第二个迭代器后面 -> 推进第一个迭代器
- 第二个迭代器在第一个迭代器后面 -> 推进第二个迭代器
- 两个迭代器在同一位置 -> 找到交集元素
在给定的示例中,使用“计数”字段作为sortKey与使用字典哈希作为键得到相同的结果。
[{'count': 351, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'}, {'count': 359, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'}]
[{'count': 351, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'}, {'count': 359, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'}]
Python单元测试
def testIntersection(self):
'''
test creating the intersection of a list of dictionaries
'''
list1 = [{'count': 351, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 332, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 336, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 359, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 309, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'}]
list2 = [{'count': 359, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 351, 'evt_datetime': datetime.datetime(2015, 10, 23, 8, 45), 'att_value': 'red'},
{'count': 381, 'evt_datetime': datetime.datetime(2015, 10, 22, 8, 45), 'att_value': 'red'}]
listi=ListOfDict.intersect(list1, list2,'count')
print(listi)
self.assertEquals(2,len(listi))
listi=ListOfDict.intersect(list1, list2)
print(listi)
self.assertEquals(2,len(listi))
ListOfDict
'''
Created on 2020-08-11
@author: wf
'''
class ListOfDict(object):
'''
https://dev59.com/BpDea4cB1Zd3GeqPgczq#33543164
'''
@staticmethod
def sortKey(d,key=None):
''' get the sort key for the given dict d with the given key
'''
if key is None:
return hash(tuple(d.items()))
else:
return d[key]
@staticmethod
def intersect(listOfDict1,listOfDict2,key=None):
'''
get the intersection lf the two lists of Dicts by the given key
'''
i1=iter(sorted(listOfDict1, key=lambda k: ListOfDict.sortKey(k, key)))
i2=iter(sorted(listOfDict2, key=lambda k: ListOfDict.sortKey(k, key)))
c1=next(i1)
c2=next(i2)
lr=[]
while True:
try:
val1=ListOfDict.sortKey(c1,key)
val2=ListOfDict.sortKey(c2,key)
if val1<val2:
c1=next(i1)
elif val1>val2:
c2=next(i2)
else:
lr.append(c1)
c1=next(i1)
c2=next(i2)
except StopIteration:
break
return lr