题
我问另一个问题:https://stackoverflow.com/questions/1180240/best-way-to-sort-1m-records-in-python 我试图确定最佳做法分类1万的记录。在我的情况下,我需要能够增加附加项目的收集和让他们使出。它建议,我尽量使用现的BTrees为这项任务。后做一些读数我有点难住了为什么数据,我会把在一组。
基本上,对于每一个记录,我有两块的数据。1.一个独特的标识图的用户和2。一个值的利用排序。
我看看,我可以添加该项目的一个OOSet作组,那里的价值,为排序上是在index0.所以, (200, 'id1'),(120, 'id2'),(400, 'id3')
和所得到的设置将被排 id2, id1 and id3
在秩序。
然而,部分要求是,各id只出现一次。我将增加额外数据设置,定期与新的数据可以包括或不包括复制'id'.如果他们重复我想要更新的价值和不增加额外的条目。因此,基于上述组,我可能会增加 (405, 'id1'),(10, 'id4')
设定和希望的输出有 id4, id2, id3, id1
在秩序。
任何建议,关于如何实现这一目标。对不起,我newbness的主题。
*编辑-额外的信息*
这里是一些实际代码从项目:
for field in lb_fields:
t = time.time()
self.data[field] = [ (v[field], k) for k, v in self.foreign_keys.iteritems() ]
self.data[field].sort(reverse=True)
print "Added %s: %03.5f seconds" %(field, (time.time() - t))
foreign_keys是原始的数据字典,每一标识作为关键和词典的额外数据的价值。数据字典中含有清单的分类数据。
作为一个侧面说明,作为每个itereation的领域中lb_fields运行,时间排序的增加不多...但它是明显的。之后,1万条记录都被分类为16个领域是使用大约4演出或RAM。最终这将在计算机上运行,与48个音乐会。
解决方案
我不认为B树或其他传统分类的数据结构(红黑树等),会帮助你,因为他们维持秩序的关键,而不是相应的值 - 换句话说,本场他们保证独特他们是为了通过同一个。你的要求是不同的,因为你要沿着一个领域的独特性,而是由其他的有序性。
什么是您的性能需求?基于Python的类型的字典的唯一性和Python的排序,在未超炫快速的笔记本电脑一个相当简单的纯Python实现,我得到5秒原有建筑(主要是一种过万台,开始与他们的字典)和约9秒,为“更新”与20,000个新的id /值对其中一半“重叠”的(因而覆盖)现有的ID和一半是新的(I可以实现更新以更快的方式,约6.5秒,但这实现了一个反常现象:如果“新”对是完全相同的“老”的人之一,这两个ID和价值,它的复制 - 对这种“identicals重复”守护就是从6.5秒推我9,和我想象你会需要同一种预防措施)。
如何远离你的要求(考虑到你在VS的2.4 GHz的Core Duo处理器,2GB的RAM运行的机器的实际速度,和一般笔记本电脑的性能问题是这些5和9秒再乘以这台笔记本电脑我使用)?督察,是它足够接近“攻击距离”值得修修补补,并试图挤过去几个周期的,或你需要的幅度更快的性能订单?
我试过其他的几种方法(用SQL数据库,用C ++和它的std ::排序&C,...),但他们都慢,所以如果你需要更高的性能,我不知道是什么你可以做的。
修改:由于运说,这表现会不错,但他不能靠近它的任何地方实现,我想我最好的表现我用来衡量这些时间的脚本...:
import gc
import operator
import random
import time
nk = 1000
def popcon(d):
for x in xrange(nk*1000):
d['id%s' % x] = random.randrange(100*1000)
def sorted_container():
ctr = dict()
popcon(ctr)
start = time.time()
ctr_sorted = ctr.items()
ctr_sorted.sort(key=operator.itemgetter(1))
stend = time.time()
return stend-start, ctr_sorted
def do_update(ctr, newones):
start = time.time()
dicol = dict(ctr)
ctr.extend((k,v) for (k,v) in newones if v!=dicol.get(k,None))
dicnu = dict(newones)
ctr.sort(key=operator.itemgetter(1))
newctr = [(k,v) for (k,v) in ctr if v==dicnu.get(k,v)]
stend = time.time()
return stend-start, newctr
def main():
random.seed(12345)
for x in range(3):
duration, ctr = sorted_container()
print 'dict-to-sorted, %d: %.2f sec, len=%d' % (x, duration, len(ctr))
newones = [('id%s' % y, random.randrange(nk*100))
for y in xrange(nk*990,nk*1010)]
duration, ctr = do_update(ctr, newones)
print 'updt-to-sorted, %d: %.2f sec, len=%d' % (x, duration, len(ctr))
del ctr
gc.collect()
main()
,这是一个典型的运行:
$ time python som.py
dict-to-sorted, 0: 5.01 sec, len=1000000
updt-to-sorted, 0: 9.78 sec, len=1010000
dict-to-sorted, 1: 5.02 sec, len=1000000
updt-to-sorted, 1: 9.12 sec, len=1010000
dict-to-sorted, 2: 5.03 sec, len=1000000
updt-to-sorted, 2: 9.12 sec, len=1010000
real 0m54.073s
user 0m52.464s
sys 0m1.258s
总经过时间是几秒钟的比我测量,显然总计多,因为它包括用于填充与随机数的容器,产生“新数据”所需要的时间也随机地,破坏和垃圾收集事情在每次运行结束时,等等。
这是与系统提供的与Mac OS X的10.5.7,2.4 GHz英特尔Core Duo处理器,和2GB的RAM一个的MacBook的Python 2.5.2(时间不改变很多,当我使用不同版本的Python)
其他提示
这是完全可以解决你的问题。为这个你应该注意的容器类型,在蟒蛇 总是 比较对象,通过调用他们的方法。因此你应该做的事情,如:
class Record:
'Combination of unique part and sort part.'
def __init__(self, unique, sort):
self.unique = unique
self.sort = sort
def __hash__(self):
# Hash should be implemented if __eq__ is implemented.
return hash(self.unique)
def __eq__(self, other):
return self.unique == other.unique
def __lt__(self, other):
return self.sort < other.sort
records = btree((Record(u, s) for u, s in zip(unique_data, sort_data)))
print(records.pop())
注:
- 这取决于如何你最喜欢的容器类型的实现,则可能需要添加的方法!=, <=,>,>=为好
- 这将不断之间的关系==及 <=只要
x.unique == y.unique
==>x.sort == y.sort