d3 = dict(d1, **d2)
Bunun sözlüğü birleştirdiğini anlıyorum. Ama benzersiz mi? Ya d1, d2 ile aynı anahtara ancak farklı değere sahipse? D1 ve d2'nin birleştirilmesini istiyorum, ancak yinelenen anahtar varsa d1'in önceliği var.
d3 = dict(d1, **d2)
Bunun sözlüğü birleştirdiğini anlıyorum. Ama benzersiz mi? Ya d1, d2 ile aynı anahtara ancak farklı değere sahipse? D1 ve d2'nin birleştirilmesini istiyorum, ancak yinelenen anahtar varsa d1'in önceliği var.
Yanıtlar:
.update()
Orijinaline artık ihtiyacınız yoksa yöntemi kullanabilirsiniz d2
:
Mevcut anahtarların üzerine yazarak sözlüğü diğerlerinden anahtar / değer çiftleriyle güncelleyin . Dönüş
None
.
Örneğin:
>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}
Güncelleme:
Elbette yeni bir birleştirilmiş sözlük oluşturmak için önce sözlüğü kopyalayabilirsiniz. Bu gerekli olabilir veya olmayabilir. Sözlüğünüzde bileşik nesneler (listeler veya sınıf örnekleri gibi diğer nesneleri içeren nesneler) copy.deepcopy
olması durumunda da dikkate alınmalıdır.
isinstance(int, object) is True
henüz deepcopy
gerekli görünmüyor.
Python2'de,
d1={'a':1,'b':2}
d2={'a':10,'c':3}
d1, d2'yi geçersiz kılar:
dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}
d2, d1'i geçersiz kılar:
dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}
Bu davranış sadece bir uygulama şansı değildir; belgelerde garanti edilmektedir :
Hem konumsal bağımsız değişkende hem de anahtar sözcük bağımsız değişkeni olarak bir anahtar belirtilirse, anahtar sözcükle ilişkili değer sözlükte tutulur.
**
tüm anahtarları dizeler olmalıdır. Daha fazlası için mail.python.org/pipermail/python-dev/2010-April/099427.html adresinden başlayan python-dev iş parçacığına bakın .
d = dict(**d1, **d2)
işe yaradığını söyleyecektim , ama yorumlarında @IoannisFilippidis'in atıfta bulunduğu şey bu. Belki de pasajı buraya dahil etmek daha net olurdu, işte burada.
Benim çözümüm bir birleştirme işlevi tanımlamak . Sofistike değil ve sadece bir satıra mal oluyor. İşte Python 3'teki kod.
from functools import reduce
from operator import or_
def merge(*dicts):
return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }
Testler
>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}
Rasgele sayıdaki sözlük argümanları için çalışır. Bu sözlükte yinelenen anahtarlar varsa, bağımsız değişken listesindeki en sağdaki sözlükteki anahtar kazanır.
.update
çağrı bulunan ( merged={}
ardından gelen for d in dict: merged.update(d)
) basit bir döngü daha kısa, daha okunaklı ve daha verimli olacaktır.
reduce
ve lambda
s, nasıl return reduce(lambda x, y: x.update(y) or x, dicts, {})
?
Trey Hunner, (python3.3 + için) ChainMap ve sözlük açma gibi birden çok sözlüğü birleştirmek için çeşitli seçenekleri özetleyen güzel bir blog gönderisine sahiptir .
Başlarken Python 3.9
, operatör |
iki sözlükten birleştirilmiş anahtarlar ve değerlerle yeni bir sözlük oluşturur:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}
Bu:
D2 ve d1'in birleştirilmiş anahtarları ve değerleriyle yeni bir sözlük d3 oluşturur. D2 ve d1 anahtarları paylaştığında d1 değerleri öncelikli olur.
Ayrıca |=
, d1 değerlerine öncelik vererek d1'i birleştirerek d2'yi değiştiren operatöre dikkat edin :
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}
Yukarıda da belirtildiği gibi kullanmanın d2.update(d1)
en iyi yaklaşım olduğuna ve d2
yine de ihtiyacınız varsa önce kopyalayabileceğinize inanıyorum .
Bununla birlikte, bunun dict(d1, **d2)
genel olarak sözlükleri birleştirmenin aslında kötü bir yolu olduğunu belirtmek isterim , çünkü anahtar kelime argümanlarının dizge olması gerekir, bu nedenle eğer dict
böyle bir şeye sahipseniz başarısız olur :
{
1: 'foo',
2: 'bar'
}
**
Tüm anahtarlard2
dizge değilse , bu numaranın anahtar kelime bağımsız değişkeninin kötüye kullanılması olarak kabul edildiğini lütfen unutmayın . Anahtarlarınd2
tümü dizge değilse , bu Python 3.2'de ve Jython, IronPython ve PyPy gibi alternatif Python uygulamalarında başarısız olur. Örneğin, mail.python.org/pipermail/python-dev/2010-April/099459.html adresine bakın .