To bardzo dziwny sposób porządkowania rzeczy. Jeśli zapisałeś w słowniku, jest to łatwe:
# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
if not url in urls_d:
urls_d[url] = 1
else:
urls_d[url] += 1
Ten kod służący do aktualizowania słownika zliczeń jest typowym „wzorcem” w Pythonie. Jest to tak powszechne, że istnieje specjalna struktura danych defaultdict
, stworzona tylko po to, aby to jeszcze ułatwić:
from collections import defaultdict # available in Python 2.5 and newer
urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1
Jeśli uzyskasz dostęp defaultdict
za pomocą klucza, a klucza nie ma jeszcze w defaultdict
, klucz zostanie automatycznie dodany z wartością domyślną. defaultdict
Bierze wywoływalnym zdałeś się i wzywa go, aby uzyskać wartość domyślną. W tym przypadku zdaliśmy w klasie int
; gdy wywołuje Python int()
, zwraca wartość zero. Tak więc, gdy po raz pierwszy odwołujesz się do adresu URL, jego liczba jest inicjowana na zero, a następnie dodajesz jeden do liczby.
Ale słownik pełen liczników jest również powszechnym wzorcem, więc Python zapewnia gotową do użycia klasę: containers.Counter
Po prostu tworzysz Counter
instancję, wywołując ją i przekazując dowolną iterowalną; tworzy słownik, w którym klucze są wartościami z elementu iterowalnego, a wartości są zliczeniami, ile razy klucz pojawił się w iterowalnym. Powyższy przykład staje się wtedy:
from collections import Counter # available in Python 2.7 and newer
urls_d = Counter(list_of_urls)
Jeśli naprawdę musisz to zrobić w sposób, który pokazałeś, najłatwiejszym i najszybszym sposobem byłoby użycie dowolnego z tych trzech przykładów, a następnie zbudowanie tego, którego potrzebujesz.
from collections import defaultdict # available in Python 2.5 and newer
urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1
urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]
Jeśli używasz Pythona 2.7 lub nowszego, możesz to zrobić w jednej linii:
from collections import Counter
urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]
Używanie wartości domyślnych działa, ale tak samo jest:
używając
.get
, możesz uzyskać domyślny zwrot, jeśli nie istnieje. Domyślnie jest to Brak, ale w przypadku, gdy Ci wysłałem, będzie to 0.źródło
Użyj defaultdict :
źródło
To zawsze działa dobrze dla mnie:
źródło
Zrobić to dokładnie po swojemu? Możesz użyć struktury for ... else
Ale jest to dość nieeleganckie. Czy naprawdę musisz przechowywać odwiedzane adresy URL jako LISTĘ? Jeśli posortujesz go jako dykt, zindeksowany na przykład przez ciąg adresu URL, będzie to o wiele czystsze:
Kilka rzeczy, na które należy zwrócić uwagę w drugim przykładzie:
urls
eliminuje potrzebę przechodzenia przez całąurls
listę podczas testowania pojedynczegourl
. To podejście będzie szybsze.dict( )
zamiast nawiasów klamrowych skraca kodlist_of_urls
,urls
iurl
jako nazwy zmiennych, aby kod dość trudne do analizowania. Lepiej znaleźć coś jaśniejszego, takich jakurls_to_visit
,urls_already_visited
icurrent_url
. Wiem, to dłużej. Ale to jest jaśniejsze.I oczywiście to zakładam
dict(url='http://www.google.fr', nbr=1)
jest to uproszczenie własnej struktury danych, ponieważ w przeciwnym razieurls
mogłoby to być po prostu:Co może stać się bardzo eleganckie przy domyślnym stanowisku:
źródło
Z wyjątkiem pierwszego razu, za każdym razem, gdy widzimy słowo, test instrukcji if kończy się niepowodzeniem. Jeśli liczysz dużą liczbę słów, wiele z nich prawdopodobnie wystąpi wielokrotnie. W sytuacji, gdy inicjalizacja wartości ma nastąpić tylko raz, a zwiększenie tej wartości nastąpi wielokrotnie, tańsze jest użycie instrukcji try:
możesz przeczytać więcej na ten temat: https://wiki.python.org/moin/PythonSpeed/PerformanceTips
źródło