Hướng dẫn python recurring string - chuỗi lặp lại python

So sánh hiệu suất lớn

Cuộn đến cuối cho đồ thị TL; DRTL;DR graph

Nội phân chính

  • So sánh hiệu suất lớn
  • Đừng phát minh lại bánh xe
  • Từ điển, bao gồm?
  • Mã đặc biệt
  • Chơi đuổi bắt
  • Sử dụng các công cụ thích hợp cho công việc
  • Thực tế đánh bại sự tinh khiết [ngoại trừ khi nó không thực sự thực tế]
  • Và người chiến thắng là...
  • Đó là tất cả mọi người
  • Cập nhật 2: Chuỗi lớn
  • Phán quyết cuối cùng: Sử dụng bộ sưu tập. Chuẩn bị trừ khi bạn không thể hoặc không muốn :]
  • Phụ lục: Numpy
  • Phụ lục 2: Một cốt truyện có phần hữu ích

Vì tôi "không có gì tốt hơn để làm" [hiểu: Tôi chỉ có rất nhiều công việc], tôi quyết định thực hiện một cuộc thi biểu diễn nhỏ. Tôi đã tập hợp các câu trả lời hợp lý hoặc thú vị nhất và đã thực hiện một số

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
8 đơn giản trong CPython 3.5.1 trên chúng. Tôi đã kiểm tra chúng chỉ với một chuỗi, đó là một đầu vào điển hình trong trường hợp của tôi:CPython 3.5.1 on them. I tested them with only one string, which is a typical input in my case:

>>> s = 'ZDXMZKMXFDKXZFKZ'
>>> len[s]
16

Xin lưu ý rằng kết quả có thể thay đổi cho các đầu vào khác nhau, có thể là độ dài khác nhau của chuỗi hoặc số lượng ký tự riêng biệt khác nhau hoặc số lần xuất hiện trung bình khác nhau trên mỗi ký tự.

Đừng phát minh lại bánh xe

Từ điển, bao gồm?

Mã đặc biệt@oefe, nice find

Chơi đuổi bắt

Sử dụng các công cụ thích hợp cho công việc

Từ điển, bao gồm?

Mã đặc biệt

Chơi đuổi bắt

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002

Sử dụng các công cụ thích hợp cho công việc

Thực tế đánh bại sự tinh khiết [ngoại trừ khi nó không thực sự thực tế]@IrshadBhat

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232

Và người chiến thắng là...

Mã đặc biệt

Chơi đuổi bắt

Sử dụng các công cụ thích hợp cho công việc@anthony

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957

Thực tế đánh bại sự tinh khiết [ngoại trừ khi nó không thực sự thực tế]

Và người chiến thắng là...@anthony

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423

Đó là tất cả mọi người
Don't do that! Or actually do. Do it now:

Cập nhật 2: Chuỗi lớn

import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]

Phán quyết cuối cùng: Sử dụng bộ sưu tập. Chuẩn bị trừ khi bạn không thể hoặc không muốn :]

Phụ lục: Numpy

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']

Phụ lục 2: Một cốt truyện có phần hữu ích

Chơi đuổi bắt

Sử dụng các công cụ thích hợp cho công việc

Thực tế đánh bại sự tinh khiết [ngoại trừ khi nó không thực sự thực tế]

Và người chiến thắng là...@Usman

>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487

Đó là tất cả mọi người

Cập nhật 2: Chuỗi lớn

Phán quyết cuối cùng: Sử dụng bộ sưu tập. Chuẩn bị trừ khi bạn không thể hoặc không muốn :]@AlexMartelli won't crucify me for

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
5

>>> timeit['''
... dd = defaultdict[int]
... for c in s:
...   dd[c] += 1
... ''', globals=locals[]]
3.3430528169992613

Phụ lục: Numpy

Phụ lục 2: Một cốt truyện có phần hữu ích@sqram

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
0

Tốt đấy. Gấp ba lần nhanh như

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
0, nhưng vẫn đủ đơn giản. Cá nhân, đây là sở thích của tôi trong trường hợp bạn không muốn thêm các ký tự mới sau này. Và ngay cả khi bạn làm, bạn vẫn có thể làm điều đó. Nó chỉ ít thuận tiện hơn so với các phiên bản khác:

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
1

Thực tế đánh bại sự tinh khiết [ngoại trừ khi nó không thực sự thực tế]

Bây giờ một chút loại quầy khác nhau. @Idank đã đưa ra một cái gì đó thú vị. Thay vì sử dụng bảng băm [từ điển a.k.a. a.k.a.

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1], chúng ta có thể tránh được nguy cơ va chạm băm và do đó chi phí giải quyết của họ. Chúng ta cũng có thể tránh chi phí băm chìa khóa và không gian bàn không có người ở. Chúng ta có thể sử dụng
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
8. Các giá trị ASCII của các ký tự sẽ là các chỉ số và số lượng của chúng sẽ là giá trị. Như @idank đã chỉ ra, danh sách này cho phép chúng tôi truy cập thời gian liên tục vào số lượng của một nhân vật. Tất cả những gì chúng ta phải làm là chuyển đổi từng ký tự từ
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
9 thành
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
0 bằng cách sử dụng hàm tích hợp
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
1. Điều đó sẽ cung cấp cho chúng tôi một chỉ mục vào danh sách, sau đó chúng tôi sẽ sử dụng để tăng số lượng của nhân vật. Vì vậy, những gì chúng tôi làm là thế này: Chúng tôi khởi tạo danh sách với số không, thực hiện công việc và sau đó chuyển đổi danh sách thành
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1.
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1 này sẽ chỉ chứa những ký tự có số lượng khác không, để làm cho nó tuân thủ các phiên bản khác.@IdanK has come up with something interesting. Instead of using a hash table [a.k.a. dictionary a.k.a.
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1], we can avoid the risk of hash collisions and consequent overhead of their resolution. We can also avoid the overhead of hashing the key, and the extra unoccupied table space. We can use a
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
8. The ASCII values of characters will be indices and their counts will be values. As @IdanK has pointed out, this list gives us constant time access to a character's count. All we have to do is convert each character from
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
9 to
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
0 using the built-in function
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
1. That will give us an index into the list, which we will then use to increment the count of the character. So what we do is this: we initialize the list with zeros, do the job, and then convert the list into a
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1. This
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1 will only contain those characters which have non-zero counts, in order to make it compliant with other versions.

Như một lưu ý phụ, kỹ thuật này được sử dụng trong thuật toán sắp xếp thời gian tuyến tính được gọi là sắp xếp đếm hoặc sắp xếp đếm. Nó rất hiệu quả, nhưng phạm vi của các giá trị được sắp xếp bị hạn chế, vì mỗi giá trị phải có bộ đếm riêng. Để sắp xếp một chuỗi các số nguyên 32 bit, sẽ cần 4,3 tỷ quầy.count sort or counting sort. It's very efficient, but the range of values being sorted is limited, since each value has to have its own counter. To sort a sequence of 32-bit integers, 4.3 billion counters would be needed.

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
2

Ouch! Không mát mẻ! Hãy thử và xem mất bao lâu khi chúng ta bỏ qua việc xây dựng từ điển.

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
3

Vẫn tệ. Nhưng chờ đã,

import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
4 là gì? Chúng ta không thể viết nó đơn giản hơn? Làm thế nào về
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
5? Đó là sạch hơn. Nhưng nó sẽ hoạt động tốt hơn?

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
4

Đáng chú ý. Bây giờ chúng ta hãy đặt từ điển trở lại.

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
5

Chậm hơn gần sáu lần. Tại sao phải mất quá lâu? Bởi vì khi chúng tôi

import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
6, chúng tôi phải kiểm tra mỗi một trong số 256 tính và xem nó có bằng không. Nhưng chúng ta đã biết số lượng nào là bằng không và cái nào không.

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
6

Nó có thể sẽ không tốt hơn thế, ít nhất là không phải là một đầu vào nhỏ như vậy. Thêm vào đó, nó chỉ có thể sử dụng cho các ký tự EASCII 8 bit. О о

Và người chiến thắng là...

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
7

Chuẩn rồi. Ngay cả khi bạn phải kiểm tra mỗi lần liệu

import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
7 có ở trong
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
8 hay không, đối với đầu vào này, đó là cách nhanh nhất. Không có dân số trước của
import time
while True:
  try:
    time.sleep[1]
  except:
    print["You're trapped in your own trap!"]
8 sẽ làm cho nó nhanh hơn [một lần nữa, cho đầu vào này]. Nó dài hơn rất nhiều so với
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
0 hoặc
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
4, nhưng cũng hiệu quả hơn.

Đó là tất cả mọi người

Bài tập nhỏ này dạy chúng ta một bài học: khi tối ưu hóa, luôn luôn đo lường hiệu suất, lý tưởng với các đầu vào dự kiến ​​của bạn. Tối ưu hóa cho trường hợp chung. Đừng cho rằng một cái gì đó thực sự hiệu quả hơn chỉ vì độ phức tạp tiệm cận của nó thấp hơn. Và cuối cùng nhưng không kém phần quan trọng, hãy tiếp tục đọc trong tâm trí. Cố gắng tìm một sự thỏa hiệp giữa "thân thiện với máy tính" và "thân thiện với con người".

CẬP NHẬT

Tôi đã được thông báo bởi @martijnpieters về hàm

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
2 có sẵn trong Python 3.@MartijnPieters of the function
import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
2 available in Python 3.

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
8

Chức năng này được thực hiện trong C, vì vậy nó sẽ nhanh hơn, nhưng hiệu suất bổ sung này có giá. Giá không tương thích với Python 2 và thậm chí có thể là phiên bản trong tương lai, vì chúng tôi đang sử dụng một chức năng riêng tư.

Từ tài liệu:

. Nó nên được coi là một chi tiết thực hiện và có thể thay đổi mà không cần thông báo trước.

Điều đó nói rằng, nếu bạn vẫn muốn tiết kiệm 620 nano giây đó cho mỗi lần lặp:

>>> timeit['Counter[s]', globals=locals[]]
8.208566107001388
9

Cập nhật 2: Chuỗi lớn

Tôi nghĩ rằng có thể là một ý tưởng tốt để chạy lại các thử nghiệm trên một số đầu vào lớn hơn, vì chuỗi 16 ký tự là một đầu vào nhỏ đến mức tất cả các giải pháp có thể khá nhanh [1.000 lần lặp trong vòng dưới 30 mili giây].

Tôi quyết định sử dụng các tác phẩm hoàn chỉnh của Shakespeare như một tập đoàn thử nghiệm, hóa ra là một thách thức khá [vì nó có kích thước trên 5mib]. Tôi chỉ sử dụng 100.000 ký tự đầu tiên của nó và tôi phải giới hạn số lần lặp từ 1.000.000 đến 1.000.

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
0

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
9 thực sự chậm trên một đầu vào nhỏ, nhưng các bảng đã quay

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
1

Naiïve θ [n2] Từ điển thời gian hiểu đơn giản là không hoạt động

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
2

Thông minh θ [n] Từ điển thời gian hiểu được hoạt động tốt

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
3

Ngoại lệ là vụng về và chậm

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
4

Bỏ qua kiểm tra loại ngoại lệ không tiết kiệm thời gian [vì ngoại lệ chỉ được ném một vài lần]

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
5

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
5 trông đẹp nhưng chạy chậm

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
6

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
6 cũng không nhanh lắm

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
7

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
7 yêu cầu đọc chuỗi [rất dài] hai lần

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
8

Sử dụng

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
8 thay vì
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1 không đẹp hay nhanh

>>> timeit['{c: s.count[c] for c in s}', globals=locals[]]
4.551155784000002
9

Để lại chuyển đổi cuối cùng thành

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1 không giúp được gì

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
0

Không quan trọng bạn xây dựng

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
8 như thế nào, vì nó không phải là nút cổ chai

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
1
>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
2

Nếu bạn chuyển đổi

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals[]]
3.3506563019982423
8 thành
>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
1 cách "thông minh", nó thậm chí còn chậm hơn [vì bạn lặp lại chuỗi hai lần]

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
3

Biến thể

>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487
4 có thể nhanh chóng cho các chuỗi nhỏ, nhưng không quá nhiều cho các chuỗi lớn

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
4

import sys
try:
  print["Goodbye. I'm going to die soon."]
  sys.exit[]
except:
  print['BACK FROM THE DEAD!!!']
2 nhanh như
>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
9 [sử dụng
>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487
7 trong nội bộ]

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
5

Phán quyết cuối cùng: Sử dụng bộ sưu tập. Chuẩn bị trừ khi bạn không thể hoặc không muốn :]

Phụ lục: Numpy

Gói

>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487
8 cung cấp một phương thức
>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487
9 hoàn thành [gần như] chính xác những gì chúng ta muốn.

Cách thức hoạt động của phương thức này rất khác với tất cả các phương pháp trên:

  • Trước tiên, nó sắp xếp một bản sao của đầu vào bằng QuickSort, đó là hoạt động thời gian O [N2] trong trường hợp xấu nhất, mặc dù O [N log n] trung bình và O [N] trong trường hợp tốt nhất.O[n2] time operation in the worst case, albeit O[n log n] on average and O[n] in the best case.

  • Sau đó, nó tạo ra một mảng "mặt nạ" chứa

    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    0 tại các chỉ số trong đó việc chạy cùng các giá trị bắt đầu, viz. tại các chỉ số nơi giá trị khác với giá trị trước đó. Các giá trị lặp đi lặp lại tạo ra
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    1 trong mặt nạ. Ví dụ:
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    2 tạo ra mặt nạ
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    3.

  • Mặt nạ này sau đó được sử dụng để trích xuất các giá trị duy nhất từ ​​đầu vào được sắp xếp -

    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    4 trong mã bên dưới. Trong ví dụ của chúng tôi, chúng sẽ là
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    5.

  • Các vị trí của các giá trị

    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    0 trong mặt nạ được đưa vào một mảng và độ dài của đầu vào được nối ở cuối mảng này. Đối với ví dụ trên, mảng này sẽ là
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    7.

  • Đối với mảng này, sự khác biệt giữa các yếu tố của nó được tính toán, ví dụ.

    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    8. Đây là các số lượng tương ứng của các phần tử trong mảng được sắp xếp -
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    9 trong mã bên dưới.

  • Cuối cùng, chúng tôi tạo ra một từ điển bằng cách zipping

    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    4 và
    >>> timeit['''
    ... dd = defaultdict[int]
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals[]]
    3.3430528169992613
    
    9:
    >>> timeit['Counter[s]', globals=locals[]]
    8.208566107001388
    
    02.

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
6

Đối với đầu vào thử nghiệm [100.000 ký tự đầu tiên của các tác phẩm hoàn chỉnh của Shakespeare], phương pháp này thực hiện tốt hơn bất kỳ thử nghiệm nào khác ở đây. Nhưng lưu ý rằng trên một đầu vào khác, phương pháp này có thể mang lại hiệu suất tồi tệ hơn các phương pháp khác. Độ sắp xếp trước của đầu vào và số lần lặp lại trên mỗi yếu tố là các yếu tố quan trọng ảnh hưởng đến hiệu suất.

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
7


Nếu bạn đang nghĩ về việc sử dụng phương pháp này vì nó nhanh gấp đôi so với

>>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
3.1484066140001232
9, hãy xem xét điều này:

  • >>> timeit['{c: s.count[c] for c in set[s]}', globals=locals[]]
    3.1484066140001232
    
    9 có độ phức tạp thời gian tuyến tính.
    >>> timeit['''
    ... d = {}
    ... for c in s:
    ...   d[c] = d.get[c, 0] + 1
    ... ''', globals=locals[]]
    3.2133633289995487
    
    9 là tuyến tính tốt nhất, bậc hai tồi tệ nhất.

  • Tăng tốc không thực sự đáng kể - bạn tiết kiệm ~ 3,5 mili giây mỗi lần lặp trên đầu vào có độ dài 100.000.

  • Sử dụng

    >>> timeit['''
    ... d = {}
    ... for c in s:
    ...   d[c] = d.get[c, 0] + 1
    ... ''', globals=locals[]]
    3.2133633289995487
    
    9 rõ ràng yêu cầu
    >>> timeit['''
    ... d = {}
    ... for c in s:
    ...   d[c] = d.get[c, 0] + 1
    ... ''', globals=locals[]]
    3.2133633289995487
    
    8.

Điều đó được xem xét, có vẻ hợp lý khi sử dụng

>>> timeit['''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals[]]
3.7060273620008957
0 trừ khi bạn cần phải thực sự nhanh chóng. Và trong trường hợp đó, bạn nên biết những gì bạn đang làm nếu không bạn sẽ chậm hơn với
>>> timeit['''
... d = {}
... for c in s:
...   d[c] = d.get[c, 0] + 1
... ''', globals=locals[]]
3.2133633289995487
8 hơn là không có nó.

Phụ lục 2: Một cốt truyện có phần hữu ích

Tôi đã chạy 13 phương pháp khác nhau ở trên trên các tiền tố của các tác phẩm hoàn chỉnh của Shakespeare và tạo ra một cốt truyện tương tác. Lưu ý rằng trong sơ đồ, cả tiền tố và thời lượng được hiển thị theo thang đo logarit [các tiền tố được sử dụng có độ dài tăng theo cấp số nhân]. Nhấp vào các mục trong truyền thuyết để hiển thị/ẩn chúng trong cốt truyện.

Bấm để mở!

Bài Viết Liên Quan

Chủ Đề