首页 > 解决方案 > 我怎样才能让这个冒泡排序更 Pythonic?

问题描述

我有这个代码:

Sorted=False
while not Sorted:
    Sorted=True
    for x,y in enumerate(List[:-1]):
        if List[x]>List[x+1]:
            List[x],List[x+1]=List[x+1],List[x]
            Sorted=False

然而使用

Sorted=True/False

重复是非常丑陋的,编写代码会更好,类似于:

while True:
    for x,y in enumerate(List[:-1]):
        if List[x]>List[x+1]:
            List[x],List[x+1]=List[x+1],List[x]
            break
    else:break

唯一的问题是,这么早从循环中中断会导致循环重复多次,从而占用更多时间。有什么办法可以让代码更加pythonic,还是我只需要让它像现在一样丑陋?

标签: pythonbubble-sortpython-3.9

解决方案


我认为没有更好的方法来以Python方式构建它。根据PEP 8的建议,我可以提出一些格式问题,这将使您的代码更易于阅读:

  • snake_case用于变量(无大写字母)
  • 分配中的空格=,逗号之后,通常在比较周围

此外,我同意Stepan 的回答,即 for 循环可以简单地使用range(len(...)). 考虑到这些(然后避免产生的保留关键字sortedlist):

done_sorting = False
while not done_sorting:
    done_sorting = True
    for i in range(len(lst - 1)):
        if lst[i] > lst[i+1]:
            lst[i], lst[i+1] = lst[i+1], lst[i]
            done_sorting = False

现在,Pythonrange(len(...))中的反模式通常是传统智慧。正如 Trey Hunner 在那篇文章中总结的那样:

如果您发现自己很想使用range(len(my_list))或循环计数器,请考虑是否可以重新定义您的问题以允许使用zipenumerate(或两者的组合)。

事实上,如果您发现自己正在使用enumerate,请考虑您是否真的需要索引。在 Python 中很少需要索引。

然而,造成这种情况的主要原因是 Python 的用于迭代和排序的内置工具数组(双关语)。如果您想纯粹作为一个实际问题对列表进行排序,那么您将使用sorted()or .sort(),而不是将自己的冒泡排序作为练习。在这种情况下,有意使用较低级别的细节,直接使用索引是有意义的。

只是为了好玩......如果你真的想以更“通常 Pythonic”的方式来做这件事,它可能看起来像这样:

done_sorting = False
while not done_sorting:
    done_sorting = True
    for (i, first), (j, second) in zip(enumerate(lst[:-1]), enumerate(lst[1:])):
        if first > second:
            lst[i], lst[j] = second, first
            done_sorting = False

而且我认为没有会争论提高可读性。


PS 这对冒泡排序没有用,因为它不能访问索引,但您可能想知道的相关内容是pairwise函数。循环列表中的连续重叠对非常方便:

for first, second in pairwise(lst):

它将包含在 Python 3.10 中itertools.pairwise,但您也可以在早期版本中使用它:

  • 它包含在可安装more-itertools包中。
  • 这些文档包括一个现成的配方,用于您自己实施它。

推荐阅读