Python - 使用min(list,key = func)的元组列表的最小值如何提高效率

时间:2016-09-04 12:17:23

标签: python list numpy tuples min

给定元组templates的列表(region, calc_3d_harmonics(region)),其中calc_3d_harmonics是为每个区域返回签名的函数,我需要找到分数最小的区域(实际得分不高)没问题。

区域的得分由calc_harmonics_distance(calc_3d_harmonics(region),query_harmonics, radius)给出,该函数计算给定某个半径的两个谐波签名之间的距离(query_harmonics和radius预先计算)。

我目前的解决方案是:

query_harmonics = calc_3d_harmonics(query_region)
ref_region, score = min(templates, key=lambda t: calc_3d_harmonics_distance(t[1], query_harmonics, radius))

团队成员建议我使用以下代码:

query_harmonics = calc_3d_harmonics(query_region)
ref_region, score = min([(t[0], calc_harmonics_distance(t[1], query_harmonics, radius)) for t in templates], key=lambda x: x[1])

注意:calc_3d_harmonicscalc_harmonics_distance都是非常缓慢而繁重的功能。此外,score可以替换为_

他声称他的建议可能会带来更好的运行时间(尽管它并不重要,因为谐波功能是主要的操作)。如果min(list, key=func)创建了一个键列表,那么我们的版本是等价的(而且我的版本更短),但是如果它每次认为我的版本都会变慢,那么它就会计算出来。

哪种方式更快?我认为必须有一个更好的(运行时间)方式来做这个(也许使用numpy?),并希望听到一些建议。

2 个答案:

答案 0 :(得分:1)

min(lst, key=func)func的每个项目上调用lst一次(这也适用于maxlist.sort和{{1}的关键功能})。因此,如果sorted包含重复项,则除非使用记忆键功能,否则键功能会执行不必​​要的工作。

为了说明,这里有一些关键函数在调用时打印它们的arg。 lst是一个普通的键函数,kf使用默认的可变字典进行记忆。

kf_cached

<强>输出

def kf(n):
    print(' Key', n)
    return int(n)

def kf_cached(n, cache={}):
    if n in cache:
        print(' Cached', n)
        return cache[n]
    print(' Key', n)
    cache[n] = k = int(n)
    return k

a = '14142'

u = max(a, key=kf)
print('max', u, '\n')

u = max(a, key=kf_cached)
print('max', u)

答案 1 :(得分:0)

如有疑问,请不要猜测,profile it

将所有代码放在后面,我们可以参考cPython实现。我们可以看到min函数使用min_max helper。 在这个助手中,我们可以找到key function is computed

的位置

最少的摘录是:

while (( item = PyIter_Next(it) )) {
    /* get the value from the key function */
    if (keyfunc != NULL) {
        val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL);
        if (val == NULL)
            goto Fail_it_item;
    }
    /* no key function; the value is the item */
    else {
        val = item;
        Py_INCREF(val);
    }
    // comparision logic for min/max
}

源代码清楚地表明,对于已排序的可迭代中的每个元素,计算一次关键函数。另一方面,排序完成后,关键功能结果被丢弃。因此,如果您计划稍后重新使用关键函数值,则可以归结为。