Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Suppose I want to find the index of the maximal value of a given sequence. In Matlab, this is:

[value, index] = max(x)

In Python, I would abstract the following pattern:

def find_best_element_index(elements, is_better):
    best_so_far = elements[0]
    best_so_far_index = 0
    for (index, element) in enumerate(elements):
        if is_better(element, best_so_far):
            best_so_far = element
            best_so_far_index = index
    return best_so_far_index

Which I could use in the following way:

import operator
assert find_best_element_index([6, 3, 9, 8, 0, 9, 7, 9, 7, 8], operator.gt) == 2

But I wonder if there is a more pythonic way to go when I just want to find the index of the "best" item.

share|improve this question

1 Answer 1

up vote 5 down vote accepted
  1. I just want to find the index of the "best" item.

This can be written very shortly and readably using enumerate, first class functions and list indexing.

def index_of_max_value(items):
    return max(enumerate(items), key = lambda x: x[1])[0]

Explanation:

  1. I create a list that contains the numbers and their indexes, the index is first, the number second.
>>> list(enumerate([4,7,4,8]))
[(0, 4), (1, 7), (2, 4), (3, 8)]
  1. I ask the item that has the biggest value when a function I decide is applied to it, I do so by passing the function as the key argument, when functions are passed around like this they are first class citizens
>>> max(["rg","gu","sd"], key = lambda s: sum(map(ord,s)))
'gu'

For example in the above I asked which of the strings had the most ASCII value.

key = lambda x: x[1]

Means that I want the pair (index,number) that has the biggest 'second' item (remember zero indexing).

  1. [n] gives you the n-th item of a list, I ask the '0-th' (first) item that is the index.

I hope that you like my alternative shorter solution, if you have any doubts, fell free to ask.

share|improve this answer
    
Great one-liner! I didn't know that I could provide an optional key argument to max. In this way, I can use max to calculate the index of the min value too! ;) –  Aristide Mar 8 at 10:33
    
BTW, can you confirm that the required size is constant, i.e., that max does not construct the whole list of couples? –  Aristide Mar 8 at 10:43
1  
@Aristide enumerate yields an iterator, that is like a promise or a lazy list, it is consumed value after value, so the space requirement are O(1), that is only two items in memory at any given time: the current max and the item to compare. –  Caridorc Mar 8 at 11:20
1  
Sorry, my question was too broad, I have edited it in order to suppress the second part, since your answer is a perfect fit for the first one. I'll ask the second question separately. Thanks for your explanations! –  Aristide Mar 8 at 12:12
    
@Aristide you are welcome! –  Caridorc Mar 8 at 19:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.