Python:"inner join"字典数组



当 list1 和 list2 的键"time"的值相同时,我目前正在使用此代码进行比较并创建一个新数组:

def innerJoin(self, list1, list2):
mergedList = []
for i in range(len(list1)):
for j in range(len(list2)):
if (list1[i]['time']==list2[j]['time']):
mergedList.append(list2[j])
return mergedList

但是,例如,当两个列表都有超过 6000 个项目时,处理时间太长。有没有办法让它更快?

在这种情况下,我可以使用 Numpy 来提高速度吗?

编辑

举个例子:

list1 =[{
'time': '2017-07-03T01:12:13Z',
'tag': 'TEMP',
'value': 34.5
},{
'time': '2017-07-03T01:12:17Z',
'tag': 'TEMP',
'value': 34
}]
list2 =[{
'time': '2017-07-03T01:12:13Z',
'tag': 'VOLUME',
'value': 3
}]

它应该返回:

mergedList =[{
'time': '2017-07-03T01:12:13Z',
'tag': 'VOLUME',
'value': 3
}]

我不需要"标签"和"代码",所以如果像这样返回就可以了:

mergedList =[{
'time': '2017-07-03T01:12:13Z'
}]

你可以尝试如下:

def innerJoin(list1, list2):
set1 = set(l['time'] for l in list1)
return [l for l in list2 if l['time'] in set1]

或者您可以使用过滤器:

...
return filter(lambda i: i['time'] in set1, list2)

你可以使用它。它要快得多:

def innerJoin(list1, list2):
mergedList = []
# Of course you can skip the sorting if you know that they are sorted
# but it is much faster even if you sort first
l1 = sorted(list1, key=lambda s:s['time'])
l2 = sorted(list2, key=lambda s:s['time'])
i1=0
i2=0
while(i1 < len(l1) and i2 < len(l2)):
if (l1[i1]['time']==l2[i2]['time']):
mergedList.append(l2[i2])
i1=i1+1
i2=i2+1
else:
if (l1[i1]['time']<l2[i2]['time']):
i1=i1+1
else:
i2=i2+1
return mergedList

你的算法是O(n²(,而我的算法是O(n(。排序可能是 O(n*log n(。knipknap 的解决方案通常更好用,但我认为这个答案可以很好地了解明智选择的算法如何影响性能。

我用 n=3,000,000 尝试了这个。当我必须对列表进行排序时,它需要 10 秒,如果我预先排序它,则需要 3.2 秒。

我想指出的是,您的代码可能存在错误,具体取决于您是否要将其视为错误。如果其中一个列表中有双峰,您将在返回的列表中获得双峰。我不知道你这背后是否有想法,但事情就是这样。我花了大约一个小时才意识到我的代码没有错。:)

如果你想使用我的代码并且确实想要该功能,你必须修改它。

最新更新