Finding the index of the maximum item from the list

Let v be a list of numbers

v = [3,5,2,4,8,6,1] 

Why does the following code to find the maximum element and its index give an error? (the 'int' object cannot be decrypted)

 reduce(lambda x,y: max(x[1],y[1]), enumerate(v)) 

PS I know that there are other ways to do this, as shown below, but I want to understand why the previous one does not work.

 max(enumerate(v), key= lambda x: x[1]) 

Epilogue

Simeon noted that my code was really wrong, because the lambda should have returned a tuple, not a number. Understanding this, my code can be easily fixed as follows:

 reduce(lambda x,y: x[1]<y[1] and y or x, enumerate(v)) 

which, by the way, is about 30% slower than

 max(enumerate(v), key= lambda x: x[1]) 
+6
source share
2 answers

You ask why the following does not work:

  reduce (lambda x, y: max (x [1], y [1]), enumerate (v))

Let's see: your input is enumerate(v) , which iterates over the following elements:

  [(0, 3), (1, 5), (2, 2), (3, 4), (4, 8), (5, 6), (6, 1)]

You intend to reduce these elements using the function lambda x,y: max(x[1],y[1]) . According to the docs , the abbreviation accepts the function as an input that applies to the two elements of the iterable. This means that it reduces two elements and returns a value that is one of the arguments of the next call to reduce.

This means that x and y are tuples. For the work above, the return value of the lambda function must be a tuple again, because it was used again at the next reduction. But you are returning an integer, the result is max . That's why you get the error message: "The object" int "is not indexed," because x[1] does not work when x is an integer.

+6
source

How reduction works:

 # type annotations: # reduce(lambda X,X:X, [X,X..]) -> X #  SAME <-- result # ↗ ↖ # SAME SAME] # ↗ ↖ # SAME SAME, # ↗ ↖ # [SAME, SAME, >>> reduce(lambda a,b:[a,b], [1,2,3,4]) [[[1, 2], 3], 4] 

Here's how seed reduction (aka fold-left) works:

 # type annotations: # reduce(lambda REDU,ELEM:REDU, [ELEM,ELEM..], seed=REDU) -> REDU # REDU <-- result # ↗ ↖ # REDU ELEM] # ↗ ↖ # REDU ELEM, # ↗ ↖ # REDU ELEM, # ↗ ↖ # REDU [ELEM, >>> reduce(lambda a,b:[a,b], [1,2,3,4], 'seed') [[[['seed', 1], 2], 3], 4] 

Do you want to:

 maxValue,maxIndex = reduce( lambda p1,p2: max(p1,p2), ((x,i) for i,x in enumerate(yourList)) ) 

An important note about reduce is the types . * When you use the abbreviation (...) with the initial value (called fold in other languages), the return type will be the seed type. * When you usually use reduce , it ignores the seed element. This works fine if all the elements in your list are of the same type (for example, you can reduce(operator.mul, [1,2,3]) or reduce(operator.add, [1,2,3]) just fine, because the reduced output type (int) is the same as the unrestored input type (two ints)). However, the return type will be the same as the type of the list item.

If your elements are of different types, you need to use reduce (...) in fold -mode (i.e. with a seed with the correct semantics). (The alternative is a special case of your lambda (very ugly).)

More specifically, your intended return type is a tuple (the maximum element and its index, or reverse). However, your reduction function is of type tuple,tuple -> int . This may not work, because it violates the contract, which reduces the requirements for your function.

+2
source

Source: https://habr.com/ru/post/912147/


All Articles