it-swarm.com.de

Python: Liste der Diktate, falls vorhanden, erhöhen Sie den Diktatwert, falls nicht, fügen Sie ein neues Diktat hinzu

Ich würde so etwas gerne machen.

list_of_urls = ['http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.cn/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.fr/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.fr/', 'http://www.google.com/', 
                'http://www.google.cn/']

urls = [{'url': 'http://www.google.fr/', 'nbr': 1}]

for url in list_of_urls:
    if url in [f['url'] for f in urls]:
         urls[??]['nbr'] += 1
    else:
         urls.append({'url': url, 'nbr': 1})

Wie kann ich ? Ich weiß nicht, ob ich das Tupel zum Bearbeiten nehmen oder die Tupel-Indizes herausfinden soll.

Irgendeine Hilfe ?

84
Natim

Das ist eine sehr seltsame Art, Dinge zu organisieren. Wenn Sie in einem Wörterbuch gespeichert haben, ist dies ganz einfach:

# 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

Dieser Code zum Aktualisieren eines Zählwörterbuchs ist ein gängiges "Muster" in Python. Es ist so üblich, dass eine spezielle Datenstruktur, defaultdict, erstellt wird, um dies noch einfacher zu machen:

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

Wenn Sie mit einem Schlüssel auf defaultdict zugreifen und der Schlüssel noch nicht in defaultdict enthalten ist, wird der Schlüssel automatisch mit einem Standardwert hinzugefügt. Das defaultdict nimmt das Callable, das Sie übergeben haben, und ruft es auf, um den Standardwert abzurufen. In diesem Fall haben wir die Klasse int übergeben. Wenn Python int() aufruft, wird ein Wert von Null zurückgegeben. Wenn Sie also zum ersten Mal auf eine URL verweisen, wird ihre Anzahl auf Null initialisiert und Sie fügen der Anzahl eine hinzu .

Ein Wörterbuch voller Zählungen ist jedoch auch ein weit verbreitetes Muster. Daher bietet Python eine einsatzbereite Klasse: containers.Counter Sie erstellen einfach eine Counter -Instanz von Ruft die Klasse auf und übergibt eine beliebige Iteration, erstellt ein Wörterbuch, in dem die Schlüssel Werte aus der Iteration sind und die Werte die Häufigkeit angeben, mit der der Schlüssel in der Iteration aufgetreten ist.

from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)

Wenn Sie es wirklich so machen müssen, wie Sie es gezeigt haben, ist es am einfachsten und schnellsten, eines dieser drei Beispiele zu verwenden und dann das gewünschte zu erstellen.

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()]

Wenn Sie Python 2.7 oder neuer verwenden, können Sie dies in einem Einzeiler tun:

from collections import Counter

urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]
174
steveha

Die Standardeinstellung funktioniert, aber auch:

urls[url] = urls.get(url, 0) + 1

mit .get, Sie können eine Standardretoure erhalten, wenn sie nicht existiert. Standardmäßig ist es None, aber in dem Fall, dass ich Ihnen gesendet habe, wäre es 0.

122
mikelikespie

Benutze defaultdict :

from collections import defaultdict

urls = defaultdict(int)

for url in list_of_urls:
    urls[url] += 1
19
Greg Hewgill

Das funktioniert bei mir immer gut:

for url in list_of_urls:
    urls.setdefault(url, 0)
    urls[url] += 1
11
mossplix

Um es genau nach deinem Geschmack zu machen? Sie könnten die for ... else-Struktur verwenden

for url in list_of_urls:
    for url_dict in urls:
        if url_dict['url'] == url:
            url_dict['nbr'] += 1
            break
    else:
        urls.append(dict(url=url, nbr=1))

Aber es ist ziemlich unelegant. Müssen Sie die besuchten URLs wirklich als LISTE speichern? Wenn Sie es als ein Diktat sortieren, das beispielsweise durch eine URL-Zeichenfolge indiziert ist, wäre es viel sauberer:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}

for url in list_of_urls:
    if url in urls:
        urls[url]['nbr'] += 1
    else:
        urls[url] = dict(url=url, nbr=1)

Ein paar Dinge, die Sie in diesem zweiten Beispiel beachten sollten:

  • sehen Sie, wie Sie mit einem Diktat für urls die gesamte urls Liste durchgehen müssen, wenn Sie nach einem einzelnen url suchen. Dieser Ansatz wird schneller sein.
  • Wenn Sie dict( ) anstelle von geschweiften Klammern verwenden, wird der Code kürzer
  • die Verwendung von list_of_urls, urls und url als Variablennamen erschwert das Parsen des Codes. Es ist besser, etwas klareres zu finden, wie urls_to_visit, urls_already_visited Und current_url. Ich weiß, es ist länger. Aber es ist klarer.

Und natürlich gehe ich davon aus, dass dict(url='http://www.google.fr', nbr=1) eine Vereinfachung Ihrer eigenen Datenstruktur ist, da urls ansonsten einfach sein könnte:

urls = {'http://www.google.fr':1}

for url in list_of_urls:
    if url in urls:
        urls[url] += 1
    else:
        urls[url] = 1

Was mit der defaultdict -Stellung sehr elegant werden kann:

urls = collections.defaultdict(int)
for url in list_of_urls:
    urls[url] += 1
3
Nicolas Dumazet

Mit Ausnahme des ersten Males schlägt der Test der if-Anweisung jedes Mal fehl, wenn ein Word angezeigt wird. Wenn Sie eine große Anzahl von Wörtern zählen, werden viele wahrscheinlich mehrmals vorkommen. In einer Situation, in der die Initialisierung eines Werts nur einmal erfolgt und die Erhöhung dieses Werts um ein Vielfaches erfolgt, ist es günstiger, eine try-Anweisung zu verwenden:

urls_d = {}
for url in list_of_urls:
    try:
        urls_d[url] += 1
    except KeyError:
        urls_d[url] = 1

sie können mehr darüber lesen: https://wiki.python.org/moin/PythonSpeed/PerformanceTips

2
pilatipus