255

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

  • 什么时候优先于另一个?
  • 哪个更有效率?多少?
  • 列表执行后是否可以恢复为未排序状态list.sort()
4

6 回答 6

396

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

sorted()适用于任何可迭代的,而不仅仅是列表。字符串、元组、字典(你会得到键)、生成器等,返回一个包含所有元素的列表,排序。

  • list.sort()当你想改变列表,sorted()当你想要一个新的排序对象时使用。sorted()当您想要对可迭代的东西进行排序时使用,不是列表。

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

  • 不,您无法检索原始位置。一旦你打电话list.sort(),原来的订单就不见了。

于 2014-03-16T20:21:27.453 回答
56

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 个整数列表的结果,正如我们在这里看到的,我们已经驳斥了旧的列表创建费用神话

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

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

在一些反馈之后,我决定另一个具有不同特征的测试是可取的。在这里,我为每次迭代 1,000 次提供相同的随机排序列表,长度为 100,000。

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当我需要对列表进行就地排序时,我会使用它,并让它决定我的用法。

于 2014-03-16T20:44:15.047 回答
15

主要区别在于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() 后可以检索列表原始位置吗?

不,因为它修改了原始列表。

于 2014-03-16T20:19:46.820 回答
5

以下是一些简单的示例,可以查看操作上的差异:

请参阅此处的数字列表:

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]
于 2018-10-30T19:12:14.267 回答
3

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

sort() 不返回任何值。

sort() 方法只是按特定顺序对给定列表的元素进行排序 - 升序或降序而不返回任何值。

sort() 方法的语法是:

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

或者,您也可以将 Python 的内置函数 sorted() 用于相同目的。排序函数返回排序列表

 list=sorted(list, key=..., reverse=...)
于 2018-12-06T13:04:37.787 回答
1

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

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

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

于 2018-04-01T14:53:48.183 回答