【问题标题】:How would I make this bubble sort more pythonic?我怎样才能让这个冒泡排序更 Pythonic?
【发布时间】:2021-07-16 22:56:33
【问题描述】:

我有这个代码:

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 还是我只需要让它保持原样?

【问题讨论】:

  • 最好在Code Review上提问
  • 使用布尔标志不会使您的代码不符合 Python 标准,有时它是表达您意图的最佳方式。对于这段代码,我跳出来的东西是大写的变量名,运算符周围没有空格,使用“List”作为变量:)

标签: python bubble-sort python-3.9


【解决方案1】:

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

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

此外,我同意 Stepan's answer 的观点,即 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

现在,Python 中的range(len(...)) is an antipattern 是普遍的常识。正如 Trey Hunner 在那篇文章中总结的那样:

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

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

然而,造成这种情况的主要原因是 Python 的用于迭代和排序的内置工具数组(双关语)。如果您想纯粹作为实际问题对列表进行排序,您将使用sorted().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

而且我认为没有人会认为这会提高可读性。


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

for first, second in pairwise(lst):

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

  • 它包含在可安装的more-itertools 包中。
  • 文档中包含一个现成的 recipe 供您自己实施。

【讨论】:

    【解决方案2】:
    1. 您的第二个版本不是冒泡排序。

    2. 我只想把循环改成

        for idx in range(len(List)-1):
           if List[idx]>List[idx+1]:
               List[idx],List[idx+1] = List[idx+1],List[idx]
               Sorted=False
      

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-25
      • 2015-07-14
      • 2021-07-09
      相关资源
      最近更新 更多