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])
Can anyone explain what this list comprehension does?
For efficiency it's a good idea to avoid repeating the slice of r
over and over
chunk = r[a:b]
[(x+a, chunk[x]) for x in xrange(len(chunk))]
I think it also makes the meaning of the code a bit clearer (it's not exactly Pythonic) yet
chunk = r[a:b]
[(i, j) for i, j in enumerate(chunk, a)]
Oh it's the identity list comprehension
list(enumerate(chunk, a))
so instead of all that waffle, you can say
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])
as @vonPetrushev tries to explain in the comments, you can replace the lambda function with an itemgetter.
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))
There isn't much performance difference and the itemgetter
version is more descriptive (as long as you know what itemgetter
does)
Let's break it down into pieces.
First, here's just the listcomp on its own:
[(x+a, r[a:b][x]) for x in xrange(len(r[a:b]))]
That's equivalent to this loop:
result=[]
for x in xrange(len(r[a:b])):
result.append((x+a, r[a:b][x]))
So, what does each part do?
r[a:b]
is the sub-sequence of r
from index a (inclusive) to b (exclusive). So len(r[a:b])
is almost a fancy way of saying ba
, but not quite—because b
could be past the end of the sequence, or either one of the indices could be negative indices. And xrange(len(r[a:b]))
is just all the numbers from 0 up to that length (again exclusive).
Now, for each of these numbers x
from 0 to that length, we create a tuple (x+a, r[a:b][x])
.
Let's work through an example:
>>> 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')
So, as you can see, it's creating a list of (index, value) for the indices from a
to b
, like this:
[(2, 'c'), (3, 'd')]
A much nicer way to write the same thing is:
>>> list(enumerate(r))[a:b]
[(2, 'c'), (3, 'd')]
… or …
>>> list(enumerate(r[a:b], a)
[(2, 'c'), (3, 'd')]
r
is a sequence, a
is a starting index, and b
is an ending index. The list comprehension will give a list of (index, r[index])
tuples where a <= index < b
. The max()
call will then return the tuple with the largest value (second item in the tuple).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.