Sự khác biệt giữa sorted(list)
vs là list.sort()
gì?
list.sort
làm thay đổi danh sách tại chỗ và trả lại None
sorted
mất bất kỳ lần lặp nào và trả về một danh sách mới, được sắp xếp.
sorted
tương đương với triển khai Python này, nhưng hàm dựng sẵn CPython sẽ chạy nhanh hơn đáng kể vì nó được viết bằng 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
Khi nào sử dụng?
- Sử dụng
list.sort
khi bạn không muốn giữ lại thứ tự sắp xếp ban đầu (Do đó bạn sẽ có thể sử dụng lại danh sách tại chỗ trong bộ nhớ.) Và khi bạn là chủ sở hữu duy nhất của danh sách (nếu danh sách được chia sẻ bởi mã khác và bạn làm thay đổi nó, bạn có thể giới thiệu các lỗi trong đó danh sách đó được sử dụng.)
- Sử dụng
sorted
khi bạn muốn giữ lại thứ tự sắp xếp ban đầu hoặc khi bạn muốn tạo một danh sách mới mà chỉ mã địa phương của bạn sở hữu.
Vị trí ban đầu của danh sách có thể được truy xuất sau list.sort () không?
Không - trừ khi bạn tự tạo một bản sao, thông tin đó sẽ bị mất vì việc sắp xếp được thực hiện tại chỗ.
"Và cái nào nhanh hơn? Và nhanh hơn bao nhiêu?"
Để minh họa hình phạt của việc tạo danh sách mới, hãy sử dụng mô-đun thời gian, đây là thiết lập của chúng tôi:
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
"""
Và đây là kết quả của chúng tôi cho một danh sách 10000 số nguyên được sắp xếp ngẫu nhiên, như chúng ta có thể thấy ở đây, chúng tôi đã bác bỏ một huyền thoại chi phí tạo danh sách cũ hơn :
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]
Con trăn 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]
Sau một số phản hồi, tôi quyết định một thử nghiệm khác sẽ được mong muốn với các đặc điểm khác nhau. Ở đây tôi cung cấp cùng một danh sách được sắp xếp ngẫu nhiên 100.000 độ dài cho mỗi lần lặp 1.000 lần.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Tôi giải thích sự khác biệt của loại lớn hơn này đến từ việc sao chép được đề cập bởi Martijn, nhưng nó không chi phối đến điểm được nêu trong câu trả lời phổ biến cũ hơn ở đây, ở đây mức tăng thời gian chỉ khoảng 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]
Tôi cũng đã chạy ở trên với một loại nhỏ hơn nhiều và thấy rằng sorted
phiên bản sao chép mới vẫn mất thời gian chạy lâu hơn khoảng 2% với độ dài 1000.
Poke cũng chạy mã của riêng mình, đây là mã:
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))
Ông đã tìm thấy loại 1000000 chiều dài, (chạy 100 lần) một kết quả tương tự, nhưng chỉ tăng khoảng 5% về thời gian, đây là đầu ra:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Phần kết luận:
Một danh sách có kích thước lớn được sắp xếp với sorted
việc tạo một bản sao có thể sẽ chi phối sự khác biệt, nhưng chính việc sắp xếp đó chi phối hoạt động và tổ chức mã của bạn xung quanh những khác biệt này sẽ là tối ưu hóa sớm. Tôi sẽ sử dụng sorted
khi tôi cần một danh sách dữ liệu được sắp xếp mới và tôi sẽ sử dụng list.sort
khi tôi cần sắp xếp danh sách tại chỗ và để điều đó xác định việc sử dụng của tôi.
sorted()
một đối số chuỗi nhưng nghĩ đó là danh sách, bạn nhận được kết quả danh sách, không phải là chuỗi : khôngsorted("abcd", reverse=True)
cho['d', 'c', 'b', 'a']
"dcba"