Hướng dẫn how do you find the count of the repeated letters in the string python? - làm thế nào để bạn tìm thấy số lượng các ký tự lặp lại trong chuỗi python?

Grand Performance Comparison

Scroll to the end for a TL;DR graph

Since I had "nothing better to do" (understand: I had just a lot of work), I decided to do a little performance contest. I assembled the most sensible or interesting answers and did some simple

>>> timeit('{c: s.count(c) for c in set(s)}', globals=locals())
3.1484066140001232
8 in 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

Be aware that results might vary for different inputs, be it different length of the string or different number of distinct characters, or different average number of occurrences per character.


Don't reinvent the wheel

Python has made it simple for us. The

>>> timeit('{c: s.count(c) for c in set(s)}', globals=locals())
3.1484066140001232
9 class does exactly what we want and a lot more. Its usage is by far the simplest of all the methods mentioned here.

taken from @oefe, nice find

>>> timeit('Counter(s)', globals=locals())
8.208566107001388

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
0 goes the extra mile, which is why it takes so long.

¿Dictionary, comprende?

Let's try using a simple

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
1 instead. First, let's do it declaratively, using dict comprehension.

I came up with this myself...

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

This will go through

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
2 from beginning to end, and for each character it will count the number of its occurrences in
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
2. Since
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
2 contains duplicate characters, the above method searches
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
2 several times for the same character. The result is naturally always the same. So let's count the number of occurrences just once for each character.

I came up with this myself, and so did @IrshadBhat

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

Better. But we still have to search through the string to count the occurrences. One search for each distinct character. That means we're going to read the string more than once. We can do better than that! But for that, we have to get off our declarativist high horse and descend into an imperative mindset.

Exceptional code

AKA Gotta catch 'em all!

inspired by @anthony

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

Well, it was worth a try. If you dig into the Python source (I can't say with certainty because I have never really done that), you will probably find that when you do

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
6, Python has to check whether the exception raised is actually of
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
7 or some other type. Just for the heck of it, let's see how long will it take if we omit that check and catch all exceptions.

made by @anthony

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

It does save some time, so one might be tempted to use this as some sort of optimization.
Don't do that! Or actually do. Do it now:

INTERLUDE 1

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

You see? It catches

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
8, besides other things. In fact, it catches all the exceptions there are. Including ones you might not have even heard about, like
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
9.

INTERLUDE 2

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

Now back to counting letters and numbers and other characters.

Playing catch-up

Exceptions aren't the way to go. You have to try hard to catch up with them, and when you finally do, they just throw up on you and then raise their eyebrows like it's your fault. Luckily brave fellows have paved our way so we can do away with exceptions, at least in this little exercise.

The

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
1 class has a nice method –
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals())
3.3506563019982423
1 – which allows us to retrieve an item from a dictionary, just like
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals())
3.3506563019982423
2. Except when the key
>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals())
3.3506563019982423
3 is not in the dictionary, it can return a default value. Let's use that method instead of fiddling with exceptions.

credit goes to @Usman

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

Almost as fast as the set-based dict comprehension. On larger inputs, this one would probably be even faster.

Use the right tool for the job

For at least mildly knowledgeable Python programmer, the first thing that comes to mind is probably

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except:
...     d[c] = 1
... ''', globals=locals())
3.3506563019982423
4. It does pretty much the same thing as the version above, except instead of a value, you give it a value factory. That might cause some overhead, because the value has to be "constructed" for each missing key individually. Let's see how it performs.

hope @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

Not that bad. I'd say the increase in execution time is a small tax to pay for the improved readability. However, we also favor performance, and we will not stop here. Let's take it further and prepopulate the dictionary with zeros. Then we won't have to check every time if the item is already there.

hats off to @sqram

>>> timeit('Counter(s)', globals=locals())
8.208566107001388
0

That's good. Over three times as fast as

>>> timeit('''
... d = {}
... for c in s:
...   try:
...     d[c] += 1
...   except KeyError:
...     d[c] = 1
... ''', globals=locals())
3.7060273620008957
0, yet still simple enough. Personally, this is my favorite in case you don't want to add new characters later. And even if you do, you can still do it. It's just less convenient than it would be in other versions:

>>> timeit('Counter(s)', globals=locals())
8.208566107001388
1

Practicality beats purity (except when it's not really practical)

Now a bit different kind of counter. @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 >>> timeit('{c: s.count(c) for c in set(s)}', globals=locals()) 3.1484066140001232 9 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
9 cung cấp một phương thức
>>> timeit('''
... dd = defaultdict(int)
... for c in s:
...   dd[c] += 1
... ''', globals=locals())
3.3430528169992613
0 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
    
    1 tại các chỉ số nơi việc chạy cùng một 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
    
    2 trong mặt nạ. Ví dụ:
    >>> timeit('''
    ... dd = defaultdict(int)
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals())
    3.3430528169992613
    
    3 tạo ra mặt nạ
    >>> timeit('''
    ... dd = defaultdict(int)
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals())
    3.3430528169992613
    
    4.

  • 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
    
    5 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
    
    6.

  • 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
    
    1 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
    
    8.

  • Đố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
    
    9. Đâ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('Counter(s)', globals=locals())
    8.208566107001388
    
    00 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
    
    5 và
    >>> timeit('Counter(s)', globals=locals())
    8.208566107001388
    
    00:
    >>> timeit('Counter(s)', globals=locals())
    8.208566107001388
    
    03.

>>> 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('''
    ... dd = defaultdict(int)
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals())
    3.3430528169992613
    
    0 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('''
    ... dd = defaultdict(int)
    ... for c in s:
    ...   dd[c] += 1
    ... ''', globals=locals())
    3.3430528169992613
    
    0 rõ ràng yêu cầu
    >>> timeit('''
    ... d = {}
    ... for c in s:
    ...   d[c] = d.get(c, 0) + 1
    ... ''', globals=locals())
    3.2133633289995487
    
    9.

Đ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
9 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.

Hướng dẫn how do you find the count of the repeated letters in the string python? - làm thế nào để bạn tìm thấy số lượng các ký tự lặp lại trong chuỗi python?

Bấm để mở!

Làm thế nào để bạn đếm số lượng chữ cái lặp lại trong một chuỗi trong Python?

Python..
chuỗi = "Trách nhiệm lớn" ;.
in ("ký tự trùng lặp trong một chuỗi đã cho:") ;.
#Count mỗi ký tự có trong chuỗi ..
cho i trong phạm vi (0, len (chuỗi)):.
Đếm = 1 ;.
cho J trong phạm vi (i+1, len (chuỗi)):.
if (chuỗi [i] == chuỗi [j] và chuỗi [i]! = ''):.
Đếm = đếm + 1 ;.

Làm cách nào để đếm số lượng ký tự lặp lại trong một chuỗi?

Approach:..
Tìm sự xuất hiện của ký tự 'A' trong chuỗi đã cho ..
Tìm số lần lặp lại được yêu cầu để tìm 'A' xảy ra ..
Nhân các chuỗi xuất hiện đơn với số ....
Nếu N cho n không phải là bội số của kích thước chuỗi đã cho thì chúng ta sẽ tìm thấy 'A' xảy ra trong phần phụ còn lại ..

Làm thế nào để bạn đếm cùng một chữ cái trong Python?

Python String Count () Phương thức đếm () trả về số lần xuất hiện của một chuỗi con trong chuỗi đã cho. The count() method returns the number of occurrences of a substring in the given string.