1
def get_max(r, a, b):
    """ Returns the maximum value in the form (index, value). """
    return max([(x+a, r[a:b][x]) for x in xrange(len(r[a:b]))], key=lambda x:x[1])

谁能解释这个列表理解的作用?

4

3 回答 3

6

为了提高效率,避免r一遍又一遍地重复切片是个好主意

chunk = r[a:b]
[(x+a, chunk[x]) for x in xrange(len(chunk))]

我认为它也使代码的含义更加清晰(它不完全是 Pythonic)

chunk = r[a:b]
[(i, j) for i, j in enumerate(chunk, a)]

哦,这是身份列表理解

list(enumerate(chunk, a))

所以你可以说,而不是那些华夫饼

def get_max(r, a, b):
    """ Returns the maximum value in the form (index, value). """
    return max(enumerate(r[a:b], a), key=lambda x:x[1])

正如@vonPetrushev 试图在评论中解释的那样,您可以用 itemgetter 替换 lambda 函数。

from operator import itemgetter
def get_max(r, a, b):
    """ Returns the maximum value in the form (index, value). """
    return max(enumerate(r[a:b], a), key=itemgetter(1))

性能差异不大,itemgetter版本更具描述性(只要您知道做什么itemgetter

于 2013-10-14T22:57:28.763 回答
1

让我们把它分解成碎片。

首先,这只是 listcomp 本身:

[(x+a, r[a:b][x]) for x in xrange(len(r[a:b]))]

这相当于这个循环:

result=[]
for x in xrange(len(r[a:b])):
    result.append((x+a, r[a:b][x]))

那么,每个部分的作用是什么?

r[a:b]r从索引 a(包括)到 b(不包括)的子序列。所以len(r[a:b])这几乎是一种花哨的说法b-a,但不完全是——因为b可能超过了序列的末尾,或者任何一个索引都可能是负索引。并且xrange(len(r[a:b]))只是从 0 到该长度的所有数字(再次独占)。

现在,对于从 0 到该长度的每个数字x,我们创建一个 tuple (x+a, r[a:b][x])

让我们看一个例子:

>>> r = ['a', 'b', 'c', 'd', 'e', 'f']
>>> a = 2
>>> b = 4
>>> r[a:b]
['c', 'd']
>>> len(r[a:b])
2
>>> list(xrange(len(r[a:b])))
[0, 1]
>>> x=0
>>> (x+a, r[a:b][x])
(2, 'c')
>>> x = 1
>>> (x+a, r[a:b][x])
(3, 'd')

因此,如您所见,它正在为从ato的索引创建一个 (index, value) 列表b,如下所示:

[(2, 'c'), (3, 'd')]

编写相同内容的更好方法是:

>>> list(enumerate(r))[a:b]
[(2, 'c'), (3, 'd')]

……或者……</p>

>>> list(enumerate(r[a:b], a)
[(2, 'c'), (3, 'd')]
于 2013-10-14T22:52:51.657 回答
1

r是一个序列,a是一个起始索引,b是一个结束索引。列表推导将给出一个(index, r[index])元组列表 where a <= index < b。然后max()调用将返回具有最大值的元组(元组中的第二项)。

于 2013-10-14T22:54:44.137 回答