繁体   English   中英

比较python中的大量字典列表

[英]Comparing massive lists of dictionaries in python

我从来没有想过我会遇到python的速度问题,但我有。 我试图根据字典值比较真正的大字典列表。 我比较两个列表,第一个像这样

biglist1=[{'transaction':'somevalue', 'id':'somevalue', 'date':'somevalue' ...}, {'transactio':'somevalue', 'id':'somevalue', 'date':'somevalue' ...}, ...]

'somevalue'代表用户生成的字符串,int或decimal。 现在,第二个列表非常相似,除了id值始终为空,因为它们尚未分配。

biglist2=[{'transaction':'somevalue', 'id':'', 'date':'somevalue' ...}, {'transactio':'somevalue', 'id':'', 'date':'somevalue' ...}, ...]

所以我想得到一个biglist2中的字典列表,它与biglist1中的字典匹配, 除了 id 之外的所有其他键。

我一直在做

for item in biglist2:
    for transaction in biglist1:
       if item['transaction'] == transaction['transaction']:
          list_transactionnamematches.append(transaction)

for item in biglist2:
    for transaction in list_transactionnamematches:
       if item['date'] == transaction['date']:
          list_transactionnamematches.append(transaction)

...等等,不比较id值,直到我得到最终的匹配列表。 由于列表可能非常大(每个项目大约3000个以上),因此python循环需要相当长的时间。

我猜这不应该是如何进行这种比较的。 有任何想法吗?

要用于查找的字段的索引。 O(N + M)

matches = []
biglist1_indexed = {}

for item in biglist1:
    biglist1_indexed[(item["transaction"], item["date"])] = item

for item in biglist2:
    if (item["transaction"], item["date"]) in biglist1_indexed:
        matches.append(item)

这可能比你现在做的快几千倍。

你想要做的是使用正确的数据结构:

  1. 创建第一个字典中其他值的元组到其id的映射字典。

  2. 在两个词典中创建两组值元组。 然后使用set操作来获取所需的元组集。

  3. 使用点1中的字典将id分配给那些元组。

原谅我生锈的python语法,已经有一段时间了,所以请考虑这部分伪代码

import operator
biglist1.sort(key=(operator.itemgetter(2),operator.itemgetter(0)))
biglist2.sort(key=(operator.itemgetter(2),operator.itemgetter(0)))
i1=0;
i2=0;
while i1 < len(biglist1) and i2 < len(biglist2):
    if (biglist1[i1]['date'],biglist1[i1]['transaction']) == (biglist2[i2]['date'],biglist2[i2]['transaction']):
        biglist3.append(biglist1[i1])
        i1++
        i2++
    elif (biglist1[i1]['date'],biglist1[i1]['transaction']) < (biglist2[i2]['date'],biglist2[i2]['transaction']):
        i1++
    elif (biglist1[i1]['date'],biglist1[i1]['transaction']) > (biglist2[i2]['date'],biglist2[i2]['transaction']):
        i2++
    else:
        print "this wont happen if i did the tuple comparison correctly"

这会将两个列表按(日期,事务)排序为相同的顺序。 然后它并排穿过它们,逐步穿过每个寻找相对相邻的比赛。 它假定(日期,交易)是独一无二的,并且我对于元组排序和比较没有完全偏离我的摇杆。

在O(m * n)......

for item in biglist2:
    for transaction in biglist1:
       if (item['transaction'] == transaction['transaction'] &&
           item['date'] == transaction['date'] &&
           item['foo'] == transaction['foo'] ) :

          list_transactionnamematches.append(transaction)

我可能采取的方法是使用一个实例变量和一个方法创建一个非常非常轻量级的类。 实例变量是指向字典的指针; 该方法重写内置的特殊方法__hash__(self) ,返回从除id之外的字典中的所有值计算的值。

从那里解决方案似乎相当明显:创建两个最初为空的字典: NM (用于无匹配匹配 。)在每个列表上完全循环一次,并为表示事务的每个字典(让我们称之为Tx_dict ),创建新类的实例( Tx_ptr )。 然后测试匹配该项目Tx_ptrNM :如果在没有匹配项N ,插入当前Tx_ptrN ; 如果N存在匹配项但M没有匹配项,则将当前Tx_ptr插入M ,其中Tx_ptr本身作为键,并且包含Tx_ptr作为值的列表; 如果NM存在匹配项,则将当前Tx_ptr附加到与M该键关联的值。

在您浏览过每个项目之后,您的字典M将包含指向与其他事务匹配的所有事务的指针,所有这些事务都整齐地组合成一个列表。

编辑 :哎呀! 显然,如果存在匹配的正确动作Tx_ptrN而不是在M是插入一个键值对到M与当前Tx_ptr为关键和价值,当前的列表Tx_ptr Tx_ptr这是已经在N

看看Psyco吧。 它是一个Python编译器,可以从您的源代码创建非常快速,优化的机器代码。

http://sourceforge.net/projects/psyco/

虽然这不是代码效率问题的直接解决方案,但它仍然可以帮助加快速度,而无需编写任何新代码。 也就是说,我仍然强烈建议尽可能优化您的代码并使用Psyco尽可能多地挤出它。

他们的部分指南专门讨论了如何使用它来加速列表,字符串和数值计算繁重的功能。

http://psyco.sourceforge.net/psycoguide/node8.html

我也是新手。 我的代码结构与他的代码大致相同。

for A in biglist:
    for B in biglist:
        if ( A.get('somekey') <> B.get('somekey') and #don't match to itself
             len( set(A.get('list')) - set(B.get('list')) ) > 10:
            [do stuff...]

这需要数小时才能运行10000个词典列表。 每个字典都包含很多内容,但我可能只需要输出id('somekey')和列表('list'),并将其重写为10000个key:value对的单个字典。

问题:这会快多少? 我认为这比使用列表列表更快,对吧?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM