从列表中查找最大元素的索引

时间:2012-03-31 23:19:12

标签: python list indexing max

设v是数字列表

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

为什么以下代码找到max元素及其索引会出错? ('int'对象不可订阅)

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

P.S。我知道还有其他方法可以做到,比如下面的那个,但我想理解为什么前一个不起作用。

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

后记

Simeon指出我的代码确实是错误的,因为lambda应该返回一个元组,而不是一个数字。理解这一点,我的代码可以通过以下方式轻松修复:

reduce(lambda x,y: x[1]<y[1] and y or x, enumerate(v))
顺便说一句,这比

慢约30%
max(enumerate(v), key= lambda x: x[1])

2 个答案:

答案 0 :(得分:6)

你问为什么以下不起作用:

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

让我们看看:您的输入是enumerate(v),它会迭代以下元素:

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

您打算使用函数lambda x,y: max(x[1],y[1])减少这些元素。根据{{​​3}},reduce将函数作为应用于iterable的两个元素的输入。这意味着它减少了两个元素并返回一个值,这是下一次reduce调用的参数之一。

这意味着xy是元组。为了使上述工作,lambda函数的返回值需要再次成为元组,因为它在下一次缩减时再次使用。但是你返回一个整数,max的结果。这就是您收到错误的原因:“'int'对象不可订阅”,因为x[1]x为整数时不起作用。

答案 1 :(得分:2)

如何减少工作:

# 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]

这是使用种子(a.k.a. fold-left)减少的方式:

# 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]

你想:

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

关于reduce的重要注意事项是类型。  *当您使用带有种子值的reduce(...)(在其他语言中称为fold)时,返回类型将是种子的类型。  *正常使用reduce时,它会忽略种子元素。如果列表中的所有元素都是相同类型(例如,您可以reduce(operator.mul, [1,2,3])reduce(operator.add, [1,2,3])就好了,这很有用,因为减少的输出类型(int)与未减少的输入类型相同(两个整体))。但是返回类型将与列表元素的类型相同。

如果您的元素属于不同类型,则需要在fold - 模式中使用reduce(...)(即使用带有右侧语义的种子)。 (另一种方法是特殊情况下你的lambda(非常难看)。)

更明确地说,您的预期返回类型是元组(最大元素及其索引,或相反)。但是,缩减函数的类型为tuple,tuple -> int。这不起作用,因为它违反了减少功能需求的合同。