我从未真正想过我会遇到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循环需要相当长的时间。
我猜这不应该是如何进行这种比较的。有什么想法吗?
答案 0 :(得分:18)
要用于查找的字段的索引。 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 :(得分:4)
您要做的是使用正确的数据结构:
创建第一个字典中其他值的元组到其id的映射字典。
在两个词典中创建两组值元组。然后使用set操作来获得你想要的元组。
使用第1点的字典为这些元组分配ID。
答案 2 :(得分:1)
原谅我生锈的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"
这将两个列表按(日期,事务)排序为相同的顺序。然后它并排穿过它们,逐步穿过每个寻找相对相邻的比赛。它假设(日期,交易)是独一无二的,并且在元组排序和比较方面,我并不完全偏离摇滚乐。
答案 3 :(得分:0)
在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)
答案 4 :(得分:0)
我可能采用的方法是使用一个实例变量和一个方法创建一个非常非常轻量级的类。实例变量是指向字典的指针;该方法重写内置特殊方法__hash__(self)
,返回从除id
之外的字典中的所有值计算的值。
从那里解决方案似乎相当明显:创建两个最初为空的词典:N
和M
(对于无匹配和匹配。 )在每个列表上只循环一次,对于表示事务的每个字典(让我们称之为Tx_dict
),创建新类的实例(Tx_ptr
)。然后在Tx_ptr
和N
中测试与M
匹配的项目:如果N
中没有匹配项,请将当前Tx_ptr
插入{{1} }};如果N
中有匹配项但N
中没有匹配项,请将当前M
插入Tx_ptr
,并将M
本身作为关键字和包含Tx_ptr
作为值的列表;如果Tx_ptr
和N
中存在匹配项,请将当前M
附加到Tx_ptr
中与该键相关联的值。
在您浏览过每个项目之后,您的词典M
将包含指向与其他交易匹配的所有交易的指针,所有这些交易都整齐地组合成一个列表。
编辑:哎呀!显然,如果M
中匹配Tx_ptr
但N
中没有匹配M
,那么正确的操作是将{8}中的键值对插入当前M
}作为键和值,列出了当前Tx_ptr
和已Tx_ptr
中的Tx_ptr
。
答案 5 :(得分:0)
看看Psyco。它是一个Python编译器,可以从您的源代码创建非常快速,优化的机器代码。
http://sourceforge.net/projects/psyco/
虽然这不是代码效率问题的直接解决方案,但它仍然可以帮助加快速度,而无需编写任何新代码。也就是说,我仍然强烈建议尽可能优化您的代码并使用Psyco尽可能快地挤出它。
他们的部分指南专门讨论了如何使用它来加速列表,字符串和数值计算繁重的功能。
答案 6 :(得分:0)
我也是新手。我的代码结构与他的代码大致相同。
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对的单个字典。
问题:这会快多少?我认为这比使用列表列表更快,对吗?