Python - 比嵌套for循环更快的东西

时间:2017-02-16 20:10:24

标签: python performance list dictionary for-loop

def fancymatching(fname1, fname2):
#This function will do much smarter and fancy kinds of compares
    if (fname1 == fname2):
        return 1
    else:
        return 0

personlist = [
{ 
'pid':'1',
'fname':'john',
'mname':'a',
'lname':'smyth',
},{ 
'pid':'2',
'fname':'john',
'mnane':'a',
'lname':'smith',
},{ 
'pid':'3',
'fname':'bob',
'mname':'b',
'lname':'nope',
}
]

for person1 in personlist:
    for person2 in personlist:
        if person1['pid'] >= person2['pid']:
            #don't check yourself, or ones that have been
        continue
        if fancymatching(person1['fname'], person2['fname']):
            print (person1['pid'] + " matched " + person2['pid'])

我正在努力改进上述代码的想法。它有效,但是如果personlist变得非常大(比如数百万),我觉得必须有比2更快的东西。

代码正在做的是获取字典列表并对每个字典的值与每个其他字典运行一个花哨的模糊匹配函数。所以它并不像将所有词典与其他词典进行比较那么简单。我想在每个字典上运行一个函数的方法,也许2个for循环是正确的方法吗?任何建议都会有所帮助!

2 个答案:

答案 0 :(得分:7)

你可以使用基本相同的双循环itertools.combinations,但迭代速度更快,因为它是用C语言编写的(只减少常数因子,你仍然有System.out.println ( "month.toString(): " + month ); System.out.println ( "output: " + output ); System.out.println ( "output2: " + output2 ); 运行时行为)不再需要O(n**2)(已经内置在if person1['pid'] >= person2['pid']: continue函数中)。

combinations

打印:

from itertools import combinations

for person1, person2 in combinations(personlist, 2):
    print(person1['fname'], person2['fname'])

但是如果您的('john', 'john') ('john', 'bob') ('john', 'bob') 允许,那么您还可以对您的值进行分组(fancymatching运行时)。例如,在您的情况下,您只匹配相同的O(n) - 值。

'fname'

但只有当你的>>> matches = {} >>> for person in personlist: ... matches.setdefault(person['fname'], []).append(person) >>> matches {'bob': [{'fname': 'bob', 'lname': 'nope', 'mname': 'b', 'pid': '3'}], 'john': [{'fname': 'john', 'lname': 'smyth', 'mname': 'a', 'pid': '1'}, {'fname': 'john', 'lname': 'smith', 'mnane': 'a', 'pid': '2'}]} 允许这样的分组时才有可能。对于你的情况,哪个是真的,但如果它更复杂则可能不是。

答案 1 :(得分:0)

添加到MSeifert的答案,如果您的匹配取决于fname1 == fname2,那么您可以对列表进行排序然后分组:ie:

from itertools import combinations, groupby

keyfunc = lambda x: x['fname']
data = sorted(personlist, key= keyfunc)
for key, group in groupby(data, key):
    #every element in group will now match
    for person1, person2 in combinations(group, 2):
        print(person1['fname'], person2['fname'])

显然,如果更改匹配功能,则需要更改键功能,以便为匹配的任何元素返回相同的值,并为不包含的元素返回不同的值。这确实依赖于存在这样一个关键函数的事实,对于任意匹配函数并不总是如此。