web-dev-qa-db-ja.com

Python:dictのリスト、存在する場合はdict値をインクリメントし、存在しない場合は新しいdictを追加します

そのようなことをしたいです。

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})

どのようにできるのか ?タプルを編集してタプルインデックスを計算する必要があるかどうかわかりませんか?

何か助け?

84
Natim

それは物事を整理する非常に奇妙な方法です。辞書に保存した場合、これは簡単です:

_# 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
_

カウントの辞書を更新するためのこのコードは、Pythonの一般的な「パターン」です。これは非常に一般的であるため、特別なデータ構造defaultdictがあり、これをさらに簡単にするために作成されています。

_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
_

キーを使用してdefaultdictにアクセスし、キーがdefaultdictにまだない場合、キーはデフォルト値で自動的に追加されます。 defaultdictは、渡された呼び出し可能オブジェクトを受け取り、それを呼び出してデフォルト値を取得します。この場合、クラスint;を渡しました。 when Python呼び出しint()はゼロの値を返します。したがって、URLを初めて参照するとき、そのカウントはゼロに初期化され、その後カウントに1を追加します。 。

しかし、カウントでいっぱいの辞書も一般的なパターンであるため、Pythonはすぐに使用できるクラスを提供します:_containers.Counter_を呼び出すだけでCounterインスタンスを作成します反復可能クラスを渡すクラス;キーが反復可能クラスの値であり、値が反復可能クラスにキーが出現した回数のカウントである辞書を作成します。

_from collections import Counter  # available in Python 2.7 and newer

urls_d = Counter(list_of_urls)
_

本当にそれを示した方法で行う必要がある場合、最も簡単で最速の方法は、これら3つの例のいずれかを使用してから、必要なものをビルドすることです。

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

Python 2.7以降を使用している場合は、ワンライナーで実行できます。

_from collections import Counter

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

デフォルトを使用すると機能しますが、次のように機能します。

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

.getを使用すると、デフォルトのリターンが存在しない場合に取得できます。デフォルトではNoneですが、送信した場合は0になります。

122
mikelikespie

defaultdict を使用します。

from collections import defaultdict

urls = defaultdict(int)

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

これは私にとって常にうまくいきます:

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

まさにあなたの方法でそれを行うには? for ... else構造を使用できます

_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))
_

しかし、それは非常に洗練されていません。訪問したURLをリストとして本当に保存する必要がありますか?たとえば、URL文字列でインデックス付けされた辞書としてソートすると、はるかにきれいになります:

_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)
_

2番目の例で注意すべきいくつかの点:

  • 単一のurlsをテストするときに、urlsの辞書を使用してurlリスト全体を調べる必要がないことを確認してください。このアプローチはより高速になります。
  • 中括弧の代わりにdict( )を使用すると、コードが短くなります
  • _list_of_urls_、urls、およびurlを変数名として使用すると、コードの解析が非常に困難になります。 _urls_to_visit_、_urls_already_visited_、_current_url_など、より明確なものを見つけることをお勧めします。私は知っている、それは長いです。しかし、それは明確です。

そしてもちろん、dict(url='http://www.google.fr', nbr=1)はあなた自身のデータ構造の単純化であると仮定しています。そうでなければ、urlsは単に

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

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

defaultdict スタンスで非常にエレガントになります:

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

初めて例外を除き、Wordが表示されるたびにifステートメントのテストが失敗します。多数の単語をカウントしている場合、多くの単語がおそらく複数回出現します。値の初期化が1回だけ発生し、その値の増加が何度も発生する状況では、tryステートメントを使用する方が安価です。

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

これについて詳しく読むことができます: https://wiki.python.org/moin/PythonSpeed/PerformanceTips

2
pilatipus