我列表中特定部分的最小数字

Posted

技术标签:

【中文标题】我列表中特定部分的最小数字【英文标题】:Smallest number in a particular part of my list 【发布时间】:2014-06-20 18:34:59 【问题描述】:

我有一个关于 python 的问题。我必须以特定方式对随机数列表进行排序(不允许使用sort())。我会尽力解释:

我必须搜索最小的数字,并将这个数字与列表中第一个位置的数字交换。

然后,我再次搜索最小的数字,但这次忽略列表中的第一个数字,因为这个数字已经排序。所以,我应该开始搜索从第二个数字(索引 1)到列表末尾的最小数字。然后找到的最小数字应该与列表中的第二个数字交换(因此索引 1)。

我希望你能理解我的问题。这是我到目前为止编写的代码,但出现错误和/或排序不正确。

array = random_integers(10,size=10)
my_list = list(array)
for i in range(len(my_list)):
    print my_list
    a = min(my_list[i:len(my_list)])
    b = my_list.index(a)
    my_list[i],my_list[b]=my_list[b],my_list[i]
    print my_list 

我认为我的范围有问题,并且

a = min(my_list[i:len(my_list)])     

我想搜索最小的数字,但不在整个列表中,我该怎么做?

【问题讨论】:

基本上你想在不使用任何内置方法的情况下对列表进行排序? 是的,我必须在不使用内置方法的情况下以这种特殊方式对列表进行排序.. 你听说过归并排序吗? en.wikipedia.org/wiki/Merge_sort 这种算法称为选择排序。它通常作为一个练习来介绍排序。 我想学习归并排序不会有什么坏处。 【参考方案1】:

问题出现在这一行:

b = my_list.index(a)

因为这会在my_listall 中搜索a 的第一次出现。如果相同的数字出现两次,那么b 将始终对应于最小的此类索引,可能小于i。所以你最终可能会移动一个已经排序的数字。

显而易见的尝试是在调用index之前对my_list进行切片:

my_list[i:].index(a)

但请注意,索引将返回介于 0N-i 之间的值。我们想要iN 之间的数字。所以一定要在结果中加上i

b = my_list[i:].index(a)+i

因此,修复现有代码的最简单方法是:

for i in range(len(my_list)):
    a = min(my_list[i:])
    b = my_list[i:].index(a)+i
    my_list[i], my_list[b] = my_list[b], my_list[i]

但请注意min 正在搜索my_list[i:] 中的所有项目,然后对index 的调用再次遍历同一个列表。您可以像这样在一次遍历中找到b

    b = min(range(i, N), key=my_list.__getitem__)

演示:

import numpy as np
array = np.random.random_integers(10,size=10)
my_list = list(array)
N = len(my_list)
for i in range(N):
    b = min(range(i, N), key=my_list.__getitem__)
    my_list[i], my_list[b] = my_list[b], my_list[i]
    print my_list

产量

[3, 10, 9, 6, 5, 3, 6, 8, 8, 4]
[3, 3, 9, 6, 5, 10, 6, 8, 8, 4]
[3, 3, 4, 6, 5, 10, 6, 8, 8, 9]
[3, 3, 4, 5, 6, 10, 6, 8, 8, 9]
[3, 3, 4, 5, 6, 10, 6, 8, 8, 9]
[3, 3, 4, 5, 6, 6, 10, 8, 8, 9]
[3, 3, 4, 5, 6, 6, 8, 10, 8, 9]
[3, 3, 4, 5, 6, 6, 8, 8, 10, 9]
[3, 3, 4, 5, 6, 6, 8, 8, 9, 10]
[3, 3, 4, 5, 6, 6, 8, 8, 9, 10]

【讨论】:

请注意,无需继续使用len(my_list)(或N)-my_list[i:] 默认在列表末尾结束。 如果你打算使用 numpy 那么为什么不使用.argmin() @Scorpion_God:我不知道 OP 是否真的想要一个以 NumPy 为中心的解决方案。毕竟,他正在实施选择排序。所以我这里只用了numpy来为OP的random_integers(10,size=10)找个意义。【参考方案2】:

如果您想要列表中的最小数字,您可以使用min()。如果您想要列表的一部分,您可以使用列表切片:my_list[1:]。将两者放在一起,您会从列表的一部分中获得最小的数字。但是,您不需要这样做,因为您可以从列表中 .pop() 代替。

sorted_list = []
while my_list:
    n = min(my_list)
    sorted_list.append(my_list.pop(my_list.index(n)))

如果您使用的是 numpy 数组,那么您可以使用 .argmin() 方法而不是 my_list.index(min(my_list))


虽然这种类型的排序有利于介绍,但效率不高。您可能需要考虑查看合并排序,以及 Python 的内置 timsort。

【讨论】:

以上是关于我列表中特定部分的最小数字的主要内容,如果未能解决你的问题,请参考以下文章

Python 3,如果列表中包含特定的东西,如何删除部分元素3 [重复]

如何在列表中获取特定值的索引 - python [重复]

如何查找特定的数字长度,并使用 Notepad++ 删除/过滤其余部分?

使用部分搜索字符串搜索联系人

如何选择 JSON 的特定部分并将其转换为使用 Moshi 改造的列表

如何选择包含特定子字符串的单词列表作为 SQL 查询(oracle)的一部分?