sorted(list)和list.sort()有什么区别?


194

list.sort()对列表进行排序并替换原始列表,而sorted(list)返回列表的排序后的副本,而不更改原始列表。

  • 什么时候比另一种更好?
  • 哪个更有效?减多少
  • list.sort()执行完列表后,可以将列表还原为未排序状态吗?

4
当心,如果您(意外地)调用sorted()了一个字符串参数,但是认为它是一个列表,则会得到一个列表结果,而不是一个字符串sorted("abcd", reverse=True)给出的['d', 'c', 'b', 'a']不是"dcba"
smci

Answers:


316

sorted()返回一个新的排序列表,而原始列表不受影响。就地list.sort()对列表进行排序,使列表索引突变,然后返回None(就像所有就地操作一样)。

sorted()适用于任何可迭代的对象,而不仅仅是列表。字符串,元组,字典(您将获得键),生成器等,返回包含所有已排序元素的列表。

  • 使用list.sort()时要变异列表中,sorted()当你想要一个新的排序的对象返回。使用sorted()时要排序的东西,是一个可迭代,而不是一个名单尚未

  • 对于列表,list.sort()它比sorted()不必创建副本要快。对于其他任何迭代,您别无选择。

  • 不,您无法检索原始位置。一旦您致电list.sort(),原始订单就消失了。


6
通常,当python函数返回时None,它是一个标志,表明操作已就位,这就是为什么当您要打印list.sort()时返回None的原因。
user1767754 '17

44

sorted(list)vs和有list.sort()什么区别?

  • list.sort 原位修改列表并返回 None
  • sorted 接受所有可迭代的并返回一个已排序的新列表。

sorted 等效于此Python实现,但是CPython内置函数应该是用C编写的,因此运行起来应可测量得更快:

def sorted(iterable, key=None):
    new_list = list(iterable)    # make a new list
    new_list.sort(key=key)       # sort it
    return new_list              # return it

什么时候使用?

  • 使用list.sort时,你不希望保留原来的排序顺序(这样你就可以重新使用内存就地列表。)当你在列表的唯一所有者(如果该名单是由其他代码和你共享对其进行更改,则可以在使用该列表的地方引入错误。)
  • 使用sorted时要创建一个新的列表,只有本地代码拥有,当你想保留原来的排序顺序或。

list.sort()之后是否可以检索列表的原始位置?

否-除非您自己进行复制,否则该信息将丢失,因为该排序是就地完成的。

“哪个更快?又快多少?”

为了说明创建新列表的代价,请使用timeit模块,这是我们的设置:

import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)]  # list of lists
for l in lists:
    random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""

这是我们随机排列的10000个整数的列表的结果,正如我们在此处看到的,我们已经证明了一个较旧的列表创建费用神话

Python 2.7

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]

Python 3

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]

经过一番反馈,我决定采用具有不同特征的另一种测试是可取的。在这里,我为每次迭代1000次提供了相同的随机排序列表,其长度为100,000,而每次迭代的次数为1000。

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""

我解释这种较大的差异是由Martijn提到的复制引起的,但是并不能支配到此处更老的答案中所指出的程度,此处的时间增加仅约10%

>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]

我还以较小的类型运行了上述内容,并且看到新的sorted副本版本在1000长度的长度上仍需要大约2%的运行时间。

Poke也运行了自己的代码,这是代码:

setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
    print(t)
    print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))

他发现长度为1000000的排序,(运行了100次)类似的结果,但时间仅增加了5%,以下是输出:

10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655

结论:

sorted进行复制并进行排序的大型列表可能会主导差异,但是排序本身将主导操作,围绕这些差异组织代码将是过早的优化。我sorted需要一个新的数据排序列表list.sort时使用,而我需要就地排序列表时使用,然后由它确定我的用法。


4
生成器设置很好,但是我不会得出结论:您破译神话的速度太快。事实仍然是sorted()必须分配一个新的列表对象并复制引用。其余代码路径相同。查看是否可以使用较大的列表运行相同的测试。只有创建列表的副本,比较一下,看看是否可以复制你发现的差异,等等
的Martijn Pieters的

11

主要区别是sorted(some_list)返回一个新的list

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified

some_list.sort()将清单排序到位

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified

请注意,由于a.sort()不返回任何内容,因此print a.sort()将打印None


list.sort()之后是否可以检索列表的原始位置?

否,因为它会修改原始列表。


1
print a.sort()将不会打印任何内容。
Burhan Khalid 2014年

1
它会打印出来None,我会澄清这一点。
基督教徒

1

.sort()函数将新列表的值直接存储在list变量中;因此,第三个问题的答案为否。另外,如果使用sorted(list)进行此操作,则可以使用它,因为它没有存储在list变量中。也有时.sort()方法充当函数,或者说它在其中接受参数。

您必须将sorted(list)的值显式存储在变量中。

同样对于短数据处理,速度没有差别。但名单很长;您应该直接使用.sort()方法进行快速工作;但是您将再次面临不可逆转的行动。


“ .sort()函数将新列表的值直接存储在列表变量中”,是吗?有什么新清单?没有新清单。该list.sort()方法对列表对象进行原位排序。
下午18年

另外,这是什么意思?“有时.sort()方法充当函数,或者说它在其中接受参数。”
下午18年

我所说的新列表是修改后的列表,而.sort()只是将修改后的列表存储到同一变量中。
Vicrobot

是的,绝对有时.sort()方法会接受参数并充当函数。我们也称它为方法,因为它是列表数据类型的属性。
Vicrobot

如果我的概念中存在某种错误,请告诉我,我将寻找它并改善我的概念,我的答案也将有所改善。谢谢
Vicrobot

1

以下是一些简单的示例,以了解操作上的区别:

请在此处查看数字列表:

nums = [1, 9, -3, 4, 8, 5, 7, 14]

调用sorted此列表时,sorted复制该列表。(意味着您的原始列表将保持不变。)

让我们来看看。

sorted(nums)

退货

[-3, 1, 4, 5, 7, 8, 9, 14]

纵观nums再次

nums

我们看到原始列表(未更改且未排序)。sorted没有更改原始列表

[1, 2, -3, 4, 8, 5, 7, 14]

采用相同的nums列表并对其应用sort功能,将更改实际列表。

让我们来看看。

从我们的nums列表开始,以确保内容仍然相同。

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()

现在原始的nums列表已更改,查看nums后,我们看到原始列表已更改并进行了排序。

nums
[-3, 1, 2, 4, 5, 7, 8, 14]

感谢您更深入地展示原始副本与副本
Brendan Metcalfe,

0

注意:sort()和sorted()之间最简单的区别是:sort()不返回任何值,而sorted()返回可迭代的列表。

sort()不返回任何值。

sort()方法仅按给定列表的元素以特定顺序排序-升序或降序,而不返回任何值。

sort()方法的语法为:

list.sort(key=..., reverse=...)

另外,您也可以出于相同目的使用Python的内置函数sorted()。排序函数返回排序列表

 list=sorted(list, key=..., reverse=...)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.