高效的Python搜索算法,用于在移动时间间隔内查找匹配

时间:2015-03-17 13:31:04

标签: python algorithm dictionary

我有一个下面的词典列表:

listofdicts = [{'Time':2015-03-14 11:54:00, 'Value':'Some Value'},
               {'Time':2015-03-14 13:23:00, 'Value':'Another Value'},
               {'Time':2015-03-14 12:52:00, 'Value':'Some Value'}, ...]

我想在列表中搜索符合以下条件的词典: 查找三个或更多具有相同Value值的词典,其中Time值彼此相差10分钟。我希望这个算法在每个字典中创建一个符合此条件的新密钥,并将其标记为匹配。

e.g. The search algorithm would find:
{'Time':2015-03-14 11:54:00, 'Value':'Same Value'}
{'Time':2015-03-14 11:56:00, 'Value':'Same Value'}
{'Time':2015-03-14 11:52:00, 'Value':'Same Value'}
and add the matching key to each dictionary:
{'Time':2015-03-14 11:54:00, 'Value':'Same Value', 'Matching':'True'}
{'Time':2015-03-14 11:56:00, 'Value':'Same Value', 'Matching':'True'}
{'Time':2015-03-14 11:52:00, 'Value':'Same Value', 'Matching':'True'}

我已经创建了一个算法来执行此操作,但它不是特别有效或可扩展。是否有人能够就如何使其更好或研究领域提出任何建议?

当前算法:

for dict in listofdicts:
   matchingdicts = []
   for dict2 in listofdicts:
      if dict['Value']==dict2['Value']:
         matchingdicts.append(dict2)
   listoftimeintervals = 
      [[dict['Time'] - datetime.timedelta(minutes=10),dict['Time']],
       [dict['Time'] - datetime.timedelta(minutes=9),dict['Time'] + datetime.timedelta(minutes=1)],
       ...,
       [dict['Time'],dict['Time'] + datetime.timedelta(minutes=10)]]
   for time in listoftimeintervals:
      dictsintimerange = []
      for matchingdict in matchingdicts:
         if time[0]<=matchingdict['Time']<=time[1]:
            dictsintimerange.append(matchingdict)
      if len(dictsintimerange)>=3:
         for eachdict in dictsintimerange:
            eachdict['Matching']=='True'

2 个答案:

答案 0 :(得分:1)

(注意:我甚至没有通过解释器运行此代码。)

首先按值对dicts进行分区。

import collections
listofdictsbyvalue = collections.defaultdict(list)
for d in listofdicts:
    listofdictsbyvalue[d['Value']].append(d)

然后按时间对每个列表进行排序并扫描。

import operator
k = 3
for lst in listofdictsbyvalue.values():
    lst.sort(key=operator.itemgetter('Time'))
    for i in range(len(lst) - (k - 1)):
        if lst[i + (k - 1)]['Time'] - lst[i]['Time'] <= datetime.timedelta(minutes=10):
            for j in range(i, i + k):
                lst[j]['Matching'] = 'True'

答案 1 :(得分:0)

首先对列表进行排序,然后按顺序扫描,在10分钟内查找项目。 大致是:

ordered = sorted(listofdicts, key=lambda e:e['Time'])
for i,value in enumerate(ordered):
    if value.get('Matching'):
        continue 
    for j in range(i+2,len(order)):
        if ordered[j]['Time'] - value['Time'] > timedelta(minutes=10):
            break
    if j-i>3:
        for x in range(i,j):
            ordered[x]['Matching']=True

对于排序,这应该是O(N lg N),对于比较,这应该是O(N)