Python, anahtarın nasıl oluşturulacağını veya anahtar için bir öğenin nasıl ekleneceğini söyledi?


161

Boş bir sözlüğüm var. Ad: dict_x Değerlerin listelendiği anahtarlara sahip olmaktır.

Ayrı bir yinelemeden bir anahtar alıyorum (ör: key_123 :) ve bir değer (bir tuple)dict_x 's değer listesine key_123.

Bu anahtar zaten varsa, bu öğeyi eklemek istiyorum. Bu anahtar yoksa, boş bir listeyle oluşturmak ve sonra listeye eklemek veya sadece bir demet ile oluşturmak istiyorum.

Gelecekte bu anahtar tekrar ortaya çıktığında, var olduğundan, değerin tekrar eklenmesini istiyorum.

Kodum şunlardan oluşur:

Anahtar ve değer alın.

Bak bakalım DEĞİL anahtar vardict_x .

ve oluşturmazsa: dict_x[key] == []

Sonradan: dict_x[key].append(value)

Bunu yapmanın yolu bu mu? try/exceptBlok kullanmaya çalışalım mı?

Yanıtlar:


254

Kullanım dict.setdefault():

dic.setdefault(key,[]).append(value)

yardım (dict.setdefault) :

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

4
Bunu eskiden yapardım dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]ama bu cevap çok daha iyi bir yol gösteriyor. Aslında set()bir argüman olarak alır ve add()yöntemi kullanmanıza izin verir ...
fatih_dur

66

İşte bunu yapmanın çeşitli yolları, böylece nasıl göründüğünü karşılaştırabilir ve ne istediğinizi seçebilirsiniz. Onları en "pitonik" olduğunu düşündüğüm bir şekilde sipariş ettim ve ilk bakışta belirgin olmayabilecek artıları ve eksileri yorumladım:

Kullanma collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Artıları: Muhtemelen en iyi performans. Eksileri: Python 2.4.x sürümünde mevcut değildir.

Kullanma dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Eksileri: Kullanılmayan list()s verimsiz oluşturulması .

Kullanma try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

Veya:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]

Merhaba, neden .setdefault gereksiz sözlükler oluşturuyor?
Phil

2
.setdefault()Gereksiz sözlükler oluşturduğunu sanmıyorum . Bence ben değilim gereksiz oluşturarak lists (yani []ikinci argüman) .setdefault()durumunda kullanılmak asla o keyzaten var. Ben dict.setdefault()(verimli anahtar karma yararına) kullanabilirsiniz ve kullanılmayan lists yeniden kullanmak için bir değişken kullanın ama bu birkaç kod satırı ekler.
antak

1
IIRC'de Python'da eşitlikteki boş bir liste bayt kodu düzeyinde sabit olarak kabul edilir, ancak bunun bir bayt kodu guru tarafından onaylanması gerekir (veya sadece disas modülünü kullanın).
gaborous

Kullanmak .setdefault, düzenli dictanahtar aramasının olmadığı bir KeyErrorsüre ile sonuçlanacak bir düzenli collections.defaultdict(list)oluşturur dict, eksik anahtar aramaları boş bir ekleyecektir list- bence istediğiniz davranışa göre seçmelisiniz
Chris_Rands

Kendi kodumda collections.defaultdict benzeri bir şey denedim ve beklenmedik yan etkileri vardı. Örneğin, şu IDLE değişimini düşünün: >>> list_dict = defaultdict (liste) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Python çağırdığında görünür Varsayılan değer, siz aktif olarak ayarlamadan anahtarı sözlüğe ekler, bu da varsayılan çok kullanılırsa çok sayıda boş liste oluşturacaktır. Sözlük için kendi sarmalayıcı işlevlerimi yuvarlayacağım, verimsiz ama umarım daha öngörülebilir.
RDBury

26

Bunun için bir defaultdict kullanabilirsiniz .

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

Bu biraz daha verimli setdefault sonunda kullanmadığınız yeni listeler oluşturmamanızdan . setdefaultÖğe sözlüğünde zaten mevcut olsa bile, yapılan her çağrı yeni bir liste oluşturur.


14

Sen kullanabilirsiniz defaultdict içindecollections .

Doc'den bir örnek:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)

0
dictionary['key'] = dictionary.get('key', []) + list_to_append

1
Bunun bazı istisnalar varlığında sahip olduğu (çok küçük) avantajı açıklamalısınız; sadece kod olarak, ek cevabın neden gerekli olduğu açık değildir.
Davis Herring

Merhaba, ek ithalat olmadan sadece bir alternatif. Bu açıkça bir if ifadesiyle yapılabilir. Ben sadece [] yerine .get () 'in gücünü kullanarak bir alternatif öneriyorum.
Tomas Silva Ebensperger

İlk iki cevap ithalatı olmayan iki farklı yoldan bahseder (olmasa da dict.get).
Davis Herring
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.