我问另一个问题: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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top