Pytanie Zliczanie powtarzających się znaków w łańcuchu w Pythonie


Chcę policzyć liczbę powtórzeń każdego znaku w ciągu znaków. Czy istnieje jakiś szczególny sposób, aby to zrobić oprócz porównywania każdego znaku ciągu od A-Z i zwiększanie licznika?

Aktualizacja (Odnosząc się do Odpowiedź Anthony'ego): Cokolwiek zasugerowałeś do tej pory, muszę napisać 26 razy. Czy istnieje prostszy sposób?


29
2018-06-13 19:37


pochodzenie


Pomocny jest również następujący wątek: stackoverflow.com/questions/992408/... - Léo Léopold Hertz 준영


Odpowiedzi:


Mój pierwszy pomysł polegał na zrobieniu tego:

chars = "abcdefghijklmnopqrstuvwxyz"
check_string = "i am checking this string to see how many times each character appears"

for char in chars:
  count = check_string.count(char)
  if count > 1:
    print char, count

To jednak nie jest dobry pomysł! To skanuje ciąg 26 razy, więc prawdopodobnie wykonasz 26 razy więcej pracy niż niektóre inne odpowiedzi. Naprawdę powinieneś to zrobić:

count = {}
for s in check_string:
  if count.has_key(s):
    count[s] += 1
  else:
    count[s] = 1

for key in count:
  if count[key] > 1:
    print key, count[key]

Gwarantuje to, że przechodzisz tylko przez ciąg, zamiast 26 razy.

Również odpowiedź Alexa jest świetna - nie znałem modułu kolekcji. Wykorzystam to w przyszłości. Jego odpowiedź jest bardziej zwięzła niż moja i technicznie lepsza. Polecam używanie jego kodu nad moim.


28
2018-06-13 19:54



Chociaż to nie twoja wina, że ​​wybrał złą odpowiedź, wyobrażam sobie, że to trochę dziwne :-D - Armandas
To jest niezręczne! Czy nie ma moderatora, który mógłby to zmienić? Próbowałem dać Alexowi kredyt - jego odpowiedź jest naprawdę lepsza. - Dan Wolchonok
Jeśli nie obsługujesz oprogramowania, które musi działać w Pythonie 2.1 lub wcześniejszym, nie musisz wiedzieć, że dict.has_key () istnieje (w wersji 2.x, nie w 3.x). W sytuacjach nieobjętych wartością defaultdict, w której chcesz sprawdzić, czy klucz znajduje się w słowniku (HINT!), Użyj np. "" "klucz adict" "" "zamiast" "" adict.has_key (klucz) "" "; wygląda lepiej i (premia!) działa szybciej (bez wyszukiwania nazw atrybutów, bez wywoływania metod). - John Machin


import collections

d = collections.defaultdict(int)
for c in thestring:
    d[c] += 1

ZA collections.defaultdict jest jak dict (podklasy, faktycznie), ale gdy wpis jest poszukiwany i nieodnaleziony, zamiast raportowania go nie ma, tworzy go i wstawia przez wywołanie dostarczonego argumentu 0-argumentu. Najpopularniejsze są defaultdict(int)do zliczania (lub równoważnie do tworzenia wielosensorowej struktury danych worka AKA), oraz defaultdict(list), która na zawsze znika z potrzeby użycia .setdefault(akey, []).append(avalue) i podobne niewygodne idiomy.

Więc kiedy już to zrobisz d jest podobnym do dyktafonu pojemnikiem mapującym każdy znak do liczby pojawiających się razy i możesz go emitować w dowolny sposób, oczywiście. Na przykład najpierw najpopularniejsza postać:

for c in sorted(d, key=d.get, reverse=True):
  print '%s %6d' % (c, d[c])

96
2018-06-13 19:51



+1 nie wiem, dlaczego wybrano inną odpowiedź ... może jeśli wyjaśnisz, co robi defaultdict? - Paolo Bergantino
Powinienem napisać bota, który odpowie na każde pytanie "defaultdict" lub "BeautifulSoup" na każde pytanie Pythona. - Triptych
@Paolo, dobry pomysł, będę edytować, aby wyjaśnić, tx. @ Triptych, tak, oni są dwie przydatne małe rzeczy ;-). - Alex Martelli
Otrzymuję następujący komunikat o błędzie po uruchomieniu kodu w systemie OS / X z moimi danymi w zmiennej ustawionej jako% thestring = "abc abc abc"% dpaste.com/55220 - Léo Léopold Hertz 준영
Love collections.defaultdict. - hughdbrown


Python 2.7+ zawiera collections.Counter klasa:

import collections
results = collections.Counter(the_string)
print(results)

27
2018-06-14 15:39



Ale jak wskazał sunqiang, collections.Counter jest również w python 2.7 i można go dodać do wcześniejszych wersji. - Michael Dunn


Jest to najkrótsza i najbardziej praktyczna rzecz, jaką mogę uzyskać bez importowania dodatkowych modułów.

text = "hello cruel world. This is a sample text"
d = dict.fromkeys(text, 0)
for c in text: d[c] += 1

print d ['a'] wyprowadziłby 2

Jest też szybki.


13
2018-06-13 20:40





Porównanie wielkich wyników

Ponieważ nie miałem "nic lepszego do roboty" (rozumiem: miałem tylko dużo pracy), zdecydowałem się zrobić mały konkurs wydajności. Złożyłem najbardziej sensowne lub interesujące odpowiedzi i zrobiłem niektóre proste timeit w CPython 3.5.1 na nich. Testowałem je tylko jednym ciągiem, który to typowy wkład w moim przypadku:

>>> s = 'ZDXMZKMXFDKXZFKZ'
>>> len(s)
16

Należy pamiętać, że wyniki mogą się różnić dla różnych danych wejściowych, niezależnie od długości ciągu znaków lub różna liczba różnych znaków lub inna średnia liczba wystąpień na znak.


Nie wymyślaj ponownie koła

Python uprościł nas. The collections.Counter klasa robi dokładnie to, co chcemy i dużo więcej. Jego użycie jest zdecydowanie najprostszą ze wszystkich wymienionych tu metod.

pochodzi z @ Oefe, miłe znalezisko

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

Counter idzie o krok dalej, dlatego tak długo trwa.

¿Słownik, comprende?

Spróbujmy użyć prostego dict zamiast. Po pierwsze, zróbmy to deklaratywnie, używając dyktowania zrozumienie.

Sam to wymyśliłem ...

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

To przejdzie s od początku do końca, a dla każdego znaku policzy liczbę jego wystąpień w s. Od s zawiera zduplikowane znaki, powyższa metoda przeszukuje s kilka razy dla tej samej postaci. Wynik jest oczywiście zawsze taki sam. Więc policzmy liczba wystąpień tylko raz dla każdej postaci.

Sam to wymyśliłem i tak też się stało @IrshadBhat


5
2018-03-29 05:40



IMHO, to powinna być zaakceptowana odpowiedź. Znakomity! - bicelot3


Chcesz użyć a dyktować.

#!/usr/bin/env python

input = "this is a string"

d = {}

for c in input:
    try:
        d[c] += 1
    except:
        d[c] = 1

for k in d.keys():
    print "%s: %d" % (k, d[k])

3
2018-06-13 19:50



to oznacza, że ​​muszę napisać oświadczenie 26 razy, aby dowiedzieć się, ile razy postać od a do z została powtórzona? - Hick
Nie. nie. - anthony


Jeśli ktoś szuka najprostszej metody bez collections moduł. Myślę, że to będzie pomocne:

>>> s = "asldaksldkalskdla"
>>> {i:s.count(i) for i in set(s)}
{'a': 4, 'd': 3, 'k': 3, 's': 3, 'l': 4}

lub

>>> [(i,s.count(i)) for i in set(s)]
[('a', 4), ('k', 3), ('s', 3), ('l', 4), ('d', 3)]

3
2017-12-27 13:22



Jedna linia jest najlepsza. - Miguel Ortiz


Możesz użyć słownika:

s = "asldaksldkalskdla"
dict = {}
for letter in s:
 if letter not in dict.keys():
  dict[letter] = 1
 else:
  dict[letter] += 1

print dict

2
2018-06-13 19:52



O (N ** 2)! Użyj "" ", jeśli litera nie w dict:" "" Działa od wersji Python 2.2. - John Machin
Uwielbiam to podczas testowania rzeczywistej wydajności, jest to w rzeczywistości najlepsza w pełni kompatybilna implementacja. Zobacz odpowiedź @kyrill powyżej. - De Novo