我正在处理找到距离的问题 - 实时连续两次使用项目之间的不同项目数。输入是从一个大文件(~10G)中读取的,但为了说明,我将使用一个小列表。
from collections import OrderedDict
unique_dist = OrderedDict()
input = [1, 4, 4, 2, 4, 1, 5, 2, 6, 2]
for item in input:
if item in unique_dist:
indx = unique_dist.keys().index(item) # find the index
unique_dist.pop(item) # pop the item
size = len(unique_dist) # find the size of the dictionary
unique_dist[item] = size - indx # update the distance value
else:
unique_dist[item] = -1 # -1 if it is new
print input
print unique_dist
正如我们所看到的,对于每个项目,我首先检查项目是否已经存在于字典中,如果是,我更新距离的值,否则我将其插入到末尾,值为-1。问题是随着规模变大,这似乎效率很低。内存不是问题,但pop
函数似乎是。我这样说是因为,如果我这样做的话:
for item in input:
unique_dist[item] = random.randint(1,99999)
程序运行得非常快。我的问题是,有什么方法可以让我的程序更高效(快速)?
编辑:
似乎真正的罪魁祸首是indx = unique_dist.keys().index(item)
。当我用indx = 1
替换它时。该计划的速度提高了几个数量级。
答案 0 :(得分:1)
根据我对cProfile
模块所做的简单分析,到目前为止最昂贵的操作是OrderedDict.__iter__()
和OrderedDict.keys()
。
以下实施的速度大约是您的7倍(根据我所做的有限测试)。
unique_dist.keys()
来避免对keys
的调用。我不完全确定,但我认为这也避免了对OrderedDict.__iter__()
的调用。len(unique_dist)
变量来避免调用size
。 (我不确定操作len(OrderedDict)
的成本是多少,但无论如何)def distance(input):
dist= []
key_set= set()
keys= []
size= 0
for item in input:
if item in key_set:
index= keys.index(item)
del keys[index]
del dist[index]
keys.append(item)
dist.append(size-index-1)
else:
key_set.add(item)
keys.append(item)
dist.append(-1)
size+= 1
return OrderedDict(zip(keys, dist))
答案 1 :(得分:0)
我修改了@Rawing的答案,以克服set
数据结构所占用的查找和插入时间所带来的开销。
from random import randint
dist = {}
input = []
for x in xrange(1,10):
input.append(randint(1,5))
keys = []
size = 0
for item in input:
if item in dist:
index = keys.index(item)
del keys[index]
keys.append(item)
dist[item] = size-index-1
else:
keys.append(item)
dist[item] = -1
size += 1
print input
print dist
答案 2 :(得分:-1)
这个怎么样:
from collections import OrderedDict
unique_dist = OrderedDict()
input = [1, 4, 4, 2, 4, 1, 5, 2, 6, 2]
for item in input:
if item in unique_dist:
indx = unique_dist.keys().index(item)
#unique_dist.pop(item) # dont't pop the item
size = len(unique_dist) # now the directory is one element to big
unique_dist[item] = size - indx - 1 # therefor decrement the value here
else:
unique_dist[item] = -1 # -1 if it is new
print input
print unique_dist
[1, 4, 4, 2, 4, 1, 5, 2, 6, 2]
OrderedDict([(1, 2), (4, 1), (2, 2), (5, -1), (6, -1)])
请注意unique_dist
中的条目现在按输入中第一次出现的项目排序;你的最后一次订购是由你订购的:
[1, 4, 4, 2, 4, 1, 5, 2, 6, 2]
OrderedDict([(4, 1), (1, 2), (5, -1), (6, -1), (2, 1)])