Python中返回数组最大元素的索引

3

我正在尝试创建一个函数,该函数返回数组的最大元素,我感觉我的代码是正确的,但语法顺序不对。我想使用for/while循环来实现。到目前为止,我有以下代码:

def manindex(arg):

    ans = 0

    while True:
    for i in range (len(arg)):
        if arg[i] > arg[ans]:
            pass

            ans = i

    return ans

如果有人能提供一些指导,我不确定我的问题在哪里,谢谢。

编辑:所以它指出我造成了一个无限循环,如果我去掉while语句,我就只剩下

def manindex(arg):

ans = 0

for i in range (len(arg)):
 if arg[i] > arg[ans]:

ans = i

return ans

但我感觉还不正确。

1
你不应同时使用它们,因为这将造成无限循环,因为“while True”语句永远不会停止。 - ZdaR
好的,如果我刪除 while true 語句,那麼剩下的就是:def manindex(arg):ans = 0 for i in range (len(arg)): if arg[i] > arg[ans]: ans = ireturn and這仍然不太對。 - Akash Nayee
如果有多个元素具有相同的最大值,该怎么办? - martineau
6个回答

7

当你说 array 时,我认为你指的是Python中的list,你根本不需要使用for/loop或while/loop来实现这一点。

你还可以使用maxindex,像这样:

xs.index(max(xs))

示例:

xs = [1,123,12,234,34,23,42,34]

xs.index(max(xs))
3

2
只是一个快速的提示:与其他答案不同,这种方法可能会两次遍历列表,一次用于最大值,一次用于索引。如果您的列表非常大,则手写循环可能更快-但请仔细测量以确保,并决定是否值得任何加速所带来的优雅损失。 - Wander Nauta
2
@WanderNauta,我完全同意索引(index)确实会引入另一个循环。 (并不是在争论,而是)我认为通过将循环(loop)从Python移动到C级别的list.index上,利用Python内置的(优雅性),值得考虑。 我认为我使用的list.index(max(list))方法可能仍然是目前其他解决方案中最快的。 - Anzel
@WanderNauta,出于好奇,我刚刚尝试了一下性能测试,假设我的列表是range(99999),%timeit结果如下:index(max) => 每次循环3.32毫秒,argmax => 每次循环8.58毫秒,max_element_index => 每次循环7毫秒。 - Anzel

1
您可以使用max函数,并将key参数设置为seq.__getitem__
def argmax(seq):
    return max(range(len(seq)), key=seq.__getitem__)

print(argmax([0,1,2,3,100,4,5]))

产生
4

1
寻找最大索引的想法始终相同,遍历数组元素,将其与当前最大值进行比较,如果更好,则当前元素的索引是最大的,否则我们继续寻找。 枚举方法
def max_element_index(items):
    max_index, max_value = None, None
    for index, item in enumerate(items):
        if item > max_value:
             max_index, max_value = index, item
    return max_index

功能式编程方法:
def max_element_index(items):
    return reduce(lambda x,y: x[1] > y[1] and x or y, 
                  enumerate(items), (None, None))[0]

冒着显得晦涩的风险,函数式方法使用reduce函数,该函数接受两个元素并决定缩减内容。这些元素是元组(索引,元素),它们是enumerate函数的结果。

在lambda体上定义的reduce函数接受两个元素并返回最大的元组。由于reduce函数会缩减直到遇到结果中只有一个元素,因此“champion”是包含最大索引和最大元素的元组,所以我们只需要访问元组的0索引就可以获取元素。

另一方面,如果列表为空,则返回None对象,这是reduce函数的第三个参数所授予的。


1
有很多答案发布了。使用“l.index(max(l))”的答案会对列表进行两次迭代。O2n。这是On和正确的方法。在这些thep问题中,使用enumerate也是正确的做法。 - Phil Cooper

1

在我写冗长的解释之前,让我先给你解决方案:

index, value = max(enumerate(list1), key=lambda x: x[1])

一行代码,高效(单次遍历O(n)),易读(我认为)。

说明

通常情况下,尽可能使用Python内置函数是一个好主意。

在这个实例中,两个关键函数是enumerate()max()


enumerate()将列表(或实际上任何可迭代对象)转换为索引和值的序列,例如:

>>> list1 = ['apple', 'banana', 'cherry']
>>> for tup in enumerate(list1):
...     print tup
...
(0, 'apple')
(1, 'banana')
(2, 'cherry')
max()接受一个可迭代对象并返回最大元素。不幸的是,max(enumerate(list1))不起作用,因为max()将基于由enumerate()创建的元组的第一个元素进行排序,而这个元素恰好是索引。 max()的一个较少知道的特性是,它可以采用第二个参数,形式为max(list1, key=something)。key是一个函数,可应用于列表中的每个值,该函数的输出就是用于确定最大值的内容。我们可以使用这个特性告诉max()按每个元组的第二个元素(即列表中包含的值)对项目进行排名。
结合enumerate()max()key(再加上一点lambda的帮助,以创建一个返回元组的第二个元素的函数),您就可以得到这个解决方案。
index, value = max(enumerate(list1), key=lambda x: x[1])

我最近想到了这个方法(并正在我的代码中随处使用),在观看雷蒙德·赫廷格的讲话将代码转化为美丽、惯用的Python后,他建议从你的代码中消除for i in xrange(len(list1)):模式。
或者,不使用lambda(感谢@sweeneyrod!):
from operator import itemgetter
index, value = max(enumerate(list1), key=itemgetter(1))

你也可以使用 operator.itemgetter(1) 来代替 lambda 函数。 - rlms
1
@sweeneyrod:谢谢,这是一个很棒的观点,已添加到答案中。 - zehnpaard

0
你可以尝试这样做。如果列表为空,则函数将返回一个错误。
m被设置为列表的第一个元素,然后我们迭代整个列表并比较每一步的值。
def findMax(xs):
    m = xs[0]
    for x in xs:
        if x > m:
            m = x
    return m

findMax([]) # 错误 findMax([1]) # 1 findMax([2,1]) # 2

如果你想使用for循环并使其更加通用,那么:

def findGeneric(pred, xs):
    m = xs[0]
    for x in xs:
        if pred(x,m):
            m = x
    return m

findGeneric(lambda a,b: len(a) > len(b), [[1],[1,1,1,1],[1,1]]) # [1,1,1,1]


寻找通用函数(lambda a,b: len(a) > len(b))在列表[[1],[1,1,1,1],[1,1]]中的结果是[1,1,1,1]。

0

我相信如果你将你的for循环改为...

for i in range (len(arg)):
    if arg[i] > ans:
        ans = arg[i]

应该可以工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接