在 Python 子列表中查找最小值的索引 - min() 返回列表中最小值的索引

时间:2021-01-09 14:30:09

标签: python sorting min sublist

我一直致力于在 Python 中实现常见的排序算法,在处理 selection sort 时,我遇到了一个问题,即查找子列表的最小值并将其与子列表的第一个值交换,从我的测试似乎是由于我在程序中使用 min() 的方式存在问题。

这是我的代码:

def selection_sort(li):
    for i in range(0, len(li)):
        a, b = i, li.index(min(li[i:]))
        li[a], li[b] = li[b], li[a]

这适用于其中包含零个重复元素的列表:

>>> selection_sort([9,8,7,6,5,4,3,2,1])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

然而,当列表中有重复元素时,它完全失败。

>>> selection_sort([9,8,8,7,6,6,5,5,5,4,2,1,1])
[8, 8, 7, 6, 6, 5, 5, 5, 4, 2, 9, 1, 1]

我试图通过检查 min() 在我的代码的第 3 行所做的事情来解决这个问题,并发现 min() 按预期返回了子列表中最小元素的索引值,但是索引是更大列表中的元素而不是子列表的元素,我希望这个实验有助于更清楚地说明:

>>> a = [1,2,1,1,2]
>>> min(a)
1                       # expected
>>> a.index(min(a))
0                       # also expected
>>> a.index(min(a[1:]))
0                       # should be 1?

我不确定是什么导致了这种行为;可以将 li[i:] 复制到临时变量 b 中,然后执行 b.index(min(b)),但是将 li[i:] 复制到 b 为每个循环可能需要很多内存和选择排序是 in-place algorithm 所以我不确定这种方法是否理想。

3 个答案:

答案 0 :(得分:1)

你没有完全正确地理解这个概念!

li.index(item) 将返回该项目在列表 li 中的第一次出现。 相反,您应该做的是,如果您在子列表中找到最小元素,则在子列表中搜索该元素,而不是在整个列表中搜索它。同样在切片列表中搜索时,您将获得关于子列表的索引。尽管您可以通过将开始步骤添加到返回的索引中来轻松解决该问题。

解决您的问题的一个小方法是:

def selection_sort(li):
    for i in range(0, len(li)):
        a, b = i, i + li[i:].index(min(li[i:]))
        li[a], li[b] = li[b], li[a]

答案 1 :(得分:0)

一种方法是使用列表理解:

idxs = [i for i, val in enumerate(a) if val == min(a)]

或者更好的是,编写自己的代码,这样渐近地更快:

idxs = []
minval = None
for i, val in enumerate(a):
    if minval is None or minval > val:
        idxs = [i]
        minval = val
    elif minval == val:
        idxs.append(i)

答案 2 :(得分:0)

当您编写 a.index(min(a[1:])) 时,您正在搜索 mina[1:] 第一次出现,但您正在在原始列表中搜索<​​/strong>。这就是您得到 0 的原因。

顺便说一下,你要找的函数一般叫argmin。它不包含在纯 python 中,但 numpy 模块包含它。