简体   繁体   English

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

[英]Find index of minimum value in a Python sublist - min() returns index of minimum value in list

I've been working on implementing common sorting algorithms into Python, and whilst working on selection sort I ran into a problem finding the minimum value of a sublist and swapping it with the first value of the sublist, which from my testing appears to be due to a problem with how I am using min() in my program.我一直致力于在 Python 中实现常见的排序算法,在进行选择排序时,我遇到了一个问题,即找到子列表的最小值并将其与子列表的第一个值交换,从我的测试来看,这似乎是由于关于我如何在我的程序中使用min()的问题。

Here is my code:这是我的代码:

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]

This works fine for lists that have zero duplicate elements within them:这适用于其中包含零重复元素的列表:

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

However, it completely fails when there are duplicate elements within the list.但是,当列表中有重复元素时,它会完全失败。

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

I tried to solve this problem by examining what min() is doing on line 3 of my code, and found that min() returns the index value of the smallest element inside the sublist as intended, but the index is of the element within the larger list rather than of the sublist, which I hope this experimentation helps to illustrate more clearly:我试图通过检查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?

I'm not sure what is causing this behaviour;我不确定是什么导致了这种行为; it could be possible to copy li[i:] into a temporary variable b and then do b.index(min(b)) , but copying li[i:] into b for each loop might require a lot of memory, and selection sort is an in-place algorithm so I am uncertain as to whether this approach is ideal.可以将li[i:]复制到临时变量b然后执行b.index(min(b)) ,但是对于每个循环将li[i:]复制到b可能需要大量 memory 和选择sort 是一种就地算法,所以我不确定这种方法是否理想。

You're not quite getting the concept correctly!你没有完全正确地理解这个概念!

li.index(item) will return the first appearance of that item in the list li. li.index(item) 将返回该项目在列表 li 中的第一次出现。 What you should do instead is if you're finding the minimum element in the sublist, search for that element in the sublist as well instead of searching it in the whole list.相反,您应该做的是,如果您在子列表中找到最小元素,请同时在子列表中搜索该元素,而不是在整个列表中搜索它。 Also when searching in the sliced list, you will get the index in respect to the sublist.此外,在切片列表中搜索时,您将获得关于子列表的索引。 Though you can easily fix that by adding the starting step to the index returned.尽管您可以通过将起始步骤添加到返回的索引来轻松解决此问题。

A small fix for your problem would be:解决您的问题的一个小方法是:

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]

One way you can do it is using list comprehension:一种方法是使用列表推导:

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

Or even better, write your own code, which is faster asymptotically:或者更好的是,编写自己的代码,渐近更快:

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)

When you write a.index(min(a[1:])) you are searching for the first occurence of the min of a[1:] , but you are searching in the original list .当您编写a.index(min(a[1:]))时,您正在搜索a[1:]min的第一次出现,但您正在原始 list中搜索。 That's why you get 0 as a result.这就是为什么你得到0结果。

By the way, the function you are looking for is generally called argmin .顺便说一句,您要查找的argmin一般称为 argmin 。 It is not contained in pure python, but numpy module has it.它不包含在纯 python 中,但numpy模块有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM