Nasıl Tek bir ifadede iki sözlükleri birleştirmek?

oy
3k

İki Python sözlükleri var ve bu iki sözlükleri döndüren tek bir ifade yazmak istiyorum, birleşti. update()Yöntem onun sonucunu döndürdü yerine yerinde bir dicti değiştirerek eğer, ne gerek olacaktır.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

Nasıl bu son birleştirilmiş dicti alabilirim zdeğil x?

(Son-bir-kazanç çatışma işleme ekstra net olmak gerekirse dict.update()ben de aradığım şey budur.)

Oluştur 02/09/2008 saat 06:44
kaynak kullanıcı
Diğer dillerde...                            


56 cevaplar

oy
40
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

Her iki sözlüklerde tuşlarıyla öğeler için ( 'b'), sen koyarak çıktısında biter hangisinin kontrol edebilirsiniz son bir.

Cevap 02/09/2008 saat 06:49
kaynak kullanıcı

oy
1k

Senin durumunda, ne yapmak is:

z = dict(x.items() + y.items())

Bu irade, bunu istediğiniz kadar son dicti koymak zve anahtarın değeri yapmak bdüzgün ikinci (geçersiz kılınabilir y) Dict değerini:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

Python 3 kullanırsanız, sadece biraz daha karmaşıktır. Oluşturmak için z:

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
Cevap 02/09/2008 saat 06:50
kaynak kullanıcı

oy
542

Bir alternatif:

z = x.copy()
z.update(y)
Cevap 02/09/2008 saat 12:00
kaynak kullanıcı

oy
269

Başka, daha özlü, opsiyon:

z = dict(x, **y)

Not : Bu popüler bir cevap olmuştur, ama eğer işaret etmek önemlidir yolmayan herhangi bir dize anahtarlarını vardır, bunların hepsi çalışıyor olması bir CPython uygulama detay kötüye olduğunu ve Python 3'te çalışmıyor, ya PyPy, IronPython veya Jython içinde. Ayrıca Guido hayranı değildir . Yani gerçekten tamamen kaçınılmalıdır anlamına ileri uyumlu veya çapraz uygulama taşınabilir kod için bu tekniği tavsiye edemez.

Cevap 02/09/2008 saat 14:52
kaynak kullanıcı

oy
85

Benzer bir şey istedim, ama yinelenen anahtarlarında değerleri birleştirildi nasıl belirleme yeteneği sayesinde, bu yüzden bu dışarı kesmek (ama ağır test etmedi). Açıkçası bu, tek bir ifade değil, ama tek bir işlev çağrıdır.

def merge(d1, d2, merge_fn=lambda x,y:y):
    """
    Merges two dictionaries, non-destructively, combining 
    values on duplicate keys as defined by the optional merge
    function.  The default behavior replaces the values in d1
    with corresponding values in d2.  (There is no other generally
    applicable merge strategy, but often you'll have homogeneous 
    types in your dicts, so specifying a merge technique can be 
    valuable.)

    Examples:

    >>> d1
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1)
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1, lambda x,y: x+y)
    {'a': 2, 'c': 6, 'b': 4}

    """
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge_fn(result[k], v)
        else:
            result[k] = v
    return result
Cevap 04/09/2008 saat 18:08
kaynak kullanıcı

oy
165

Bu muhtemelen popüler bir cevap olmayacak, ancak neredeyse kesinlikle bunu yapmak istemiyoruz. Eğer bir birleştirme var kopyasını istiyorsanız, kopyayı kullanın (ya deepcopy , ne istediğinize bağlı olarak) ve daha sonra güncelleyin. Daha fazla Pythonic - - iki kod satırları daha okunabilir .items () + .items () ile tek hat oluşturma daha. Açık örtülü daha iyidir.

Eğer .items kullandığınızda ek olarak, (), sen dict öğeleri içeren yeni bir liste oluştururken (Python 3.0 pre). senin sözlükleri büyükse, o zaman ki (en kısa sürede birleştirilmiş dict oluşturulan olarak atılmasına benzer iki büyük listeleri) havai oldukça çok olduğunu. ikinci dict yoluyla öğeyi-by-öğeye çalıştırabilirsiniz çünkü update () daha verimli çalışabilir.

Açısından zaman :

>>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.52571702003479
>>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.694622993469238
>>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
41.484580039978027

IMO ilk ikisi arasındaki minik yavaşlama okunabilirlik için buna değer. () Ve güncelleme () eski sürümlerde çalışacak kopya oysa ek olarak, sözlük yaratılması için anahtar kelime argümanlar sadece, Python 2.3 eklenmiştir.

Cevap 08/09/2008 saat 10:16
kaynak kullanıcı

oy
114

Bir takip cevap olarak, bu iki alternatifin nispi performansı hakkında sorular:

z1 = dict(x.items() + y.items())
z2 = dict(x, **y)

Benim makinede, en azından (oldukça sıradan x86_64 koşu Python 2.5.2) günü alternatif z2önemli ölçüde daha hızlı da sadece daha kısa ve daha basit bir şey değildir. Sen kullanarak kendiniz için bu doğrulayabilir timeitPython ile gelir modülü.

Örnek 1: Belirli sözlükleri eşleme kendilerine 20 ardışık tamsayılardır:

% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())'
100000 loops, best of 3: 5.67 usec per loop
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)' 
100000 loops, best of 3: 1.53 usec per loop

z23,5 ya da öylesine kat kazanır. Farklı sözlükleri oldukça farklı sonuçlar görünüyor, ama z2her zaman kazanmada avantajlı görünüyor. (Sizin için tutarsız sonuçlar alırsanız aynı testte, geçen deneyin -rbüyük varsayılan 3. den bir sayı ile)

Örnek 2: örtüşmeyen sözlükleri eşleme tamsayı ve tersi 252 kısa şeritler:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())'
1000 loops, best of 3: 260 usec per loop
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)'               
10000 loops, best of 3: 26.9 usec per loop

z2 Kitabımda oldukça büyük bir galibiyet 10 yaklaşık bir faktörle kazanır!

Eğer o ikisini karşılaştırarak sonra merak z1'kötü performans bu varyasyon iyi çalışabilir merak sırayla götürdü iki öğe listeleri, inşa etmenin yükü isnat edilebilir s:

from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))

Birkaç hızlı testler, örneğin

% python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))'
10000 loops, best of 3: 66 usec per loop

sonucuna bana yol z3biraz daha hızlıdır z1ancak neredeyse kadar hızlı, z2. Tüm ekstra yazarak değer Kesinlikle.

Kullanarak: Bu tartışma hala iki listeyi birleştirme "bariz" yolu ile bu alternatiflerin performans karşılaştırma önemli bir şey eksik, updateyöntemi. Aşağıdaki gibi, ben yerinde değiştirerek yerine x'in bir kopyasını yapacağım x veya y modifiye hiçbiri ifadeleri ile eşit düzeyde tutmak için denemek için:

z0 = dict(x)
z0.update(y)

Tipik bir sonuç:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)'
10000 loops, best of 3: 26.9 usec per loop

Başka bir deyişle, z0ve z2esasen aynı performansa sahip görünmektedir. Bunun bir tesadüf olabilir mi? Yapmıyorum....

Aslında, saf Python kodu bundan daha iyi yapmak için imkansız olduğunu iddia edecek kadar ileri gider. Eğer bir C uzatma modülünde önemli ölçüde daha iyi yapabilir eğer, ben Python millet iyi Python çekirdek içine kodunuzu (veya yaklaşım bir varyasyonu) içeren ilginizi çekebilir düşünün. Python kullanan dictpek çok yeri; faaliyetlerini optimize büyük bir anlaşma.

Ayrıca bu yazabiliriz

z0 = x.copy()
z0.update(y)

Tony, ama olarak (doğal) gösterimde fark performansı üzerinde herhangi ölçülebilir bir etkiye sahip olmadığı ortaya çıktı. size doğru bakar onu kullanın. Tabii ki, o iki tablo versiyonu anlamak çok daha kolay olduğunu işaret etmek, tamamen doğru.

Cevap 23/10/2008 saat 01:38
kaynak kullanıcı

oy
54

en iyi sürüm olacağım kopyasını kullanarak değil iken düşünebildiğim:

from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))

Bu daha hızlıdır dict(x.items() + y.items())ancak kadar hızlı değil n = copy(a); n.update(b), en azından CPython üzerinde. Eğer değiştirirseniz Bu sürüm ayrıca Python 3 çalışır iteritems()için items()otomatik 2to3 aracı tarafından yapılır, hangi.

ben bir tek fonksiyonel sözdiziminde istediğini oldukça iyi açıklar çünkü Şahsen ben en iyi bu sürümü gibi. sadece küçük sorun y x alınan değerler önceliklidir gelen değer verdiğini tamamen bariz yapmaz, ama bunu anlamaya zordur inanmıyorum olmasıdır.

Cevap 14/10/2010 saat 17:55
kaynak kullanıcı

oy
34

soru zaten birkaç kez cevap olsa da, sorunun bu basit çözüm henüz listelenmemesi.

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)

Bu z0 ve yukarıda belirtilen kötülük z2, ama kolay anlaşılır ve değişim kadar hızlıdır.

Cevap 14/10/2011 saat 15:12
kaynak kullanıcı

oy
24

Eğer lambda'lar sonra kötü olduğunu düşünüyorum Eğer daha fazla okuyun. İstendiği gibi, bir ifade ile hızlı ve bellek verimli bir çözüm yazabilirsiniz:

x = {'a':1, 'b':2}
y = {'b':10, 'c':11}
z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y)
print z
{'a': 1, 'c': 11, 'b': 10}
print x
{'a': 1, 'b': 2}

Gibi iki satır kullanarak, yukarıda önerilen veya bir işlev yazma muhtemelen gitmek için daha iyi bir yoldur.

Cevap 23/11/2011 saat 16:08
kaynak kullanıcı

oy
59

Recursively / derin bir dicti güncellemek

def deepupdate(original, update):
    """
    Recursively update a dict.
    Subdict's won't be overwritten but also updated.
    """
    for key, value in original.iteritems(): 
        if key not in update:
            update[key] = value
        elif isinstance(value, dict):
            deepupdate(value, update[key]) 
    return update

gösteri:

pluto_original = {
    'name': 'Pluto',
    'details': {
        'tail': True,
        'color': 'orange'
    }
}

pluto_update = {
    'name': 'Pluutoo',
    'details': {
        'color': 'blue'
    }
}

print deepupdate(pluto_original, pluto_update)

Çıktılar:

{
    'name': 'Pluutoo',
    'details': {
        'color': 'blue',
        'tail': True
    }
}

Teşekkür düzenlemeler için rednaw.

Cevap 29/11/2011 saat 09:52
kaynak kullanıcı

oy
10

Cevaplar bunun için iyi olmalarına rağmen sığ sözlük, burada tanımlanan yöntemlerin hiçbiri aslında derin bir sözlük birleştirme yapmak.

Örnekler izleyin:

a = { 'one': { 'depth_2': True }, 'two': True }
b = { 'one': { 'extra': False } }
print dict(a.items() + b.items())

Bir böyle bir şeyin bir sonucu beklenir:

{ 'one': { 'extra': False', 'depth_2': True }, 'two': True }

Bunun yerine, bu olsun:

{'two': True, 'one': {'extra': False}}

'Tek' giriş gerçekten bir birleştirme olsaydı onun sözlüğe içindeki öğeler olarak 'depth_2' ve 'ekstra' olmalıydı.

Ayrıca zincirini kullanarak, çalışmaz:

from itertools import chain
print dict(chain(a.iteritems(), b.iteritems()))

Sonuçlar içinde:

{'two': True, 'one': {'extra': False}}

O rcwesick da verdi derin birleştirme aynı sonucu yaratır.

Evet, örnek sözlükler birleştirmek için çalışacağını, ancak bunların hiçbiri birleştirmek için genel bir mekanizmadır. Ben gerçek bir birleştirme yapan bir yöntem yazmak kez daha sonra bu güncelleyeceğiz.

Cevap 03/08/2012 saat 22:36
kaynak kullanıcı

oy
31
def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

Böyle gölgeli ve şüpheli cevapları arasında, bu parlayan bir örnek hayatı için diktatör tarafından onaylanan bir ve Python dicts birleştirmek için sadece iyi yoludur Guido van Rossum kendisi! Başka biri bu yarısını önerdi ancak bir fonksiyon içine koymadı.

print dict_merge(
      {'color':'red', 'model':'Mini'},
      {'model':'Ferrari', 'owner':'Carl'})

verir:

{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
Cevap 06/08/2012 saat 08:24
kaynak kullanıcı

oy
12

İki sözlükler

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

n sözlükleri

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))

sumKötü performansa sahiptir. Bkz https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/

Cevap 17/10/2012 saat 01:09
kaynak kullanıcı

oy
70

Python 3, kullanabileceğiniz collections.ChainMap tek güncelleştirilebilir görünümü oluşturmak için hangi grupların birden dicts veya birlikte diğer eşleştirmeleri:

>>> from collections import ChainMap
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = ChainMap({}, y, x)
>>> for k, v in z.items():
        print(k, '-->', v)

a --> 1
b --> 10
c --> 11
Cevap 28/04/2013 saat 02:15
kaynak kullanıcı

oy
5

Bir dict anlama sen edebilir kullanma

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

dc = {xi:(x[xi] if xi not in list(y.keys()) 
           else y[xi]) for xi in list(x.keys())+(list(y.keys()))}

verir

>>> dc
{'a': 1, 'c': 11, 'b': 10}

Sözdizimi unutmayın if elseanlama içinde

{ (some_key if condition else default_key):(something_if_true if condition 
          else something_if_false) for key, value in dict_.items() }
Cevap 27/05/2013 saat 08:04
kaynak kullanıcı

oy
-3

Burada, tamam çalışmak için bazı kod gibi görünüyor:

def merge(d1, d2, mode=0):
    if not type(d2) is dict:
        raise Exception("d2 is not a dict")

    if not type(d1) is dict:
        if mode == 0:
            raise Exception("d1 is not a dict")
        return d2

    result = dict(d1)

    for k, v in d2.iteritems():
        if k in result and type(v) is dict:
            result[k] = merge(result[k], v, 1)
        else:
            if mode == 1:
                result.update(d2)
            else:
                result[k] = v
    return result
Cevap 11/07/2013 saat 06:13
kaynak kullanıcı

oy
8

Burada fikirler üzerinde Çizim ve başka yerlerde ben bir işlevi kavramış ettik:

def merge(*dicts, **kv): 
      return { k:v for d in list(dicts) + [kv] for k,v in d.items() }

Kullanımı (piton 3 test edilmiştir):

assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\
    {1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'})

assert (merge(foo='bar')=={'foo': 'bar'})

assert (merge({1:11},{1:99},foo='bar',baz='quux')==\
    {1: 99, 'foo': 'bar', 'baz':'quux'})

assert (merge({1:11},{1:99})=={1: 99})

Onun yerine bir lambda kullanabilirsiniz.

Cevap 19/07/2013 saat 04:49
kaynak kullanıcı

oy
14

Için tek ifadesi çözümüne açan Kötüye Matthew cevap :

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (lambda f=x.copy(): (f.update(y), f)[1])()
>>> z
{'a': 1, 'c': 11, 'b': 10}

Sen bir ifadeyi istediğini söyledi ben istismar lambdalambda sağladığı tek ifadesi sınırını geçersiz kılmak için bir ad bağlamak için, ve küpe. Yaltaklanmak için çekinmeyin.

Eğer kopyalayarak umurumda değil durumunda da elbette yapabilirsiniz:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
Cevap 07/08/2013 saat 20:23
kaynak kullanıcı

oy
1

**Kopya sayısı aslında daha yüksektir yapıyor demektir bir ara dicti yaratır dict(one, **two)formu, ama çok büyük bir kopya sayısı (ya da muhtemelen olmadığı sürece C olur hepsi o takdirde, itertools giderek daha genellikle daha hızlı hala yüzden kopya) çok pahalıdır. Her zaman olduğu gibi aslında hız veriyorsan size kullanım örneğini zaman aşımına gerekir.

Boş bir dict ile Python 2.7.3 üzerinde Zamanlama:

$ python -m timeit "dict({}, **{})"
1000000 loops, best of 3: 0.405 usec per loop

$ python -m timeit -s "from itertools import chain" \
    "dict(chain({}.iteritems(), {}.iteritems()))"
1000000 loops, best of 3: 1.18 usec per loop

10,000 (küçük) eşyalarla:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(10000)}' \
    "dict(d, **d)"
1000 loops, best of 3: 550 usec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(10000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
1000 loops, best of 3: 1.11 msec per loop

100.000 öğelerle:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(100000)}' \
    "dict(d, **d)"
10 loops, best of 3: 19.6 msec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(100000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
10 loops, best of 3: 20.1 msec per loop

1.000.000 öğelerle:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(1000000)}' \
    "dict(d, **d)"
10 loops, best of 3: 273 msec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(1000000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
10 loops, best of 3: 233 msec per loop
Cevap 06/09/2013 saat 19:18
kaynak kullanıcı

oy
18

Python3 olarak, itemsyöntem, herhangi bir artık bir listesini verir , fakat daha ziyade bir görünümü , bir dizi gibi hareket eder. Bu durumda sizinle birleştirerek beri seti birliği almak gerekir +çalışmaz:

dict(x.items() | y.items())

2.7 sürümünden python3 benzeri davranışları için viewitemsyöntem yerine çalışmalıdır items:

dict(x.viewitems() | y.viewitems())

o (başlık gösterdiği gibi) bir dizi sendika operasyonu yerine birleştirme gibi düşünmek daha doğal görünüyor çünkü zaten bu notasyonu tercih ederim.

Düzenle:

Piton 3. Birinci için daha fazla puan Birkaç, dikkat dict(x, **y)anahtarlar sürece hile piton 3 çalışmaz ydizelerdir.

Ayrıca, Raymond Hettinger en Chainmap cevabı o argümanları olarak dicts isteğe bağlı sayıda alabilir, ancak bu yana, oldukça şık dokümanlardan sıralı olarak gerçekleştirilen her arama için tüm dicts listesi bakar gibi görünür:

anahtar bulunana kadar Aramaları arda yatan eşleştirmeleri arayın.

uygulamanızda birçok tarama varsa, bu sizi yavaşlatabilir:

In [1]: from collections import ChainMap
In [2]: from string import ascii_uppercase as up, ascii_lowercase as lo; x = dict(zip(lo, up)); y = dict(zip(up, lo))
In [3]: chainmap_dict = ChainMap(y, x)
In [4]: union_dict = dict(x.items() | y.items())
In [5]: timeit for k in union_dict: union_dict[k]
100000 loops, best of 3: 2.15 µs per loop
In [6]: timeit for k in chainmap_dict: chainmap_dict[k]
10000 loops, best of 3: 27.1 µs per loop

aramalar için yavaş büyüklükte bir sipariş yaklaşık Yani. Ben Chainmap hayranıyım, ama birçok aramaları olabilir nerede daha az pratik görünüyor.

Cevap 09/10/2013 saat 17:09
kaynak kullanıcı

oy
9
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x, z = dict(x), x.update(y) or x
>>> x
{'a': 1, 'b': 2}
>>> y
{'c': 11, 'b': 10}
>>> z
{'a': 1, 'c': 11, 'b': 10}
Cevap 13/11/2013 saat 08:01
kaynak kullanıcı

oy
6

Bugüne kadar sıralanan çözümlerle sahip sorun birleştirilmiş sözlükte, anahtar "b" değeri 10'dur, yani ancak, Benim düşünceme göre, bu ışığında 12. olmalı, şu takdim:

import timeit

n=100000
su = """
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
"""

def timeMerge(f,su,niter):
    print "{:4f} sec for: {:30s}".format(timeit.Timer(f,setup=su).timeit(n),f)

timeMerge("dict(x, **y)",su,n)
timeMerge("x.update(y)",su,n)
timeMerge("dict(x.items() + y.items())",su,n)
timeMerge("for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] ",su,n)

#confirm for loop adds b entries together
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]
print "confirm b elements are added:",x

Sonuçlar:

0.049465 sec for: dict(x, **y)
0.033729 sec for: x.update(y)                   
0.150380 sec for: dict(x.items() + y.items())   
0.083120 sec for: for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]

confirm b elements are added: {'a': 1, 'c': 11, 'b': 12}
Cevap 03/12/2013 saat 16:11
kaynak kullanıcı

oy
2

Ben (Adam ı piton SEVİYORUM :-)) burada belirtilmemiş bir çözüm

z = {}
z.update(x) or z.update(y)

Bu y yanı sıra x güncelleme olmayacaktır. Performans? Ben, daha ziyade yavaş olacak :-) sanmıyorum

NOT: 'veya' operasyonu değil 've' operasyon olması gerekiyordu. kodunu düzeltmek için Düzenlendi.

Cevap 05/12/2013 saat 06:02
kaynak kullanıcı

oy
4

O hala çok aptal .updateşey döndürür.
Sadece sorunu çözmek için basit bir yardımcı işlevini kullanın:

def merge(dict1,*dicts):
    for dict2 in dicts:
        dict1.update(dict2)
    return dict1

Örnekler:

merge(dict1,dict2)
merge(dict1,dict2,dict3)
merge(dict1,dict2,dict3,dict4)
merge({},dict1,dict2)  # this one returns a new copy
Cevap 01/03/2014 saat 23:44
kaynak kullanıcı

oy
1

OP'ın iki sözlükler bir birlik gibi bir şey olacaktır:

{'a': 1, 'b': 2, 10, 'c': 11}

Özellikle, iki varlık (birliği xve y) tüm unsurları içeren xve / veya y. Ne yazık ki, neyi OP sorar bir birlik yazının başlığı rağmen değil.

Aşağıda Kodum zarif ne de bir tek satırlık ne olduğunu, ama birliğin anlamı ile tutarlı olduğuna inanıyoruz.

OP'ın Örneğin Gönderen:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

z = {}
for k, v in x.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))
for k, v in y.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))

{'a': [1], 'b': [2, 10], 'c': [11]}

tek istediği İster listeleri değişti edilebilir, ancak bir sözlük ya sözlükte değerler olarak listelerini (ve iç içe listeleri) içeriyorsa yukarıdaki çalışacaktır.

Cevap 30/09/2014 saat 01:36
kaynak kullanıcı

oy
3k

Nasıl Tek bir ifadede iki Python sözlükleri birleştirebilirsiniz?

Sözlüklerde için xve y, zgelen değerlerle birleştirilmiş sözlük haline ygelenler değiştirilmesi x.

  • Python 3.5 veya daha büyük ise,:

    z = {**x, **y}
    
  • Python 2, (ya da 3.4 ya da daha düşük) bir fonksiyonu geç:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values
        z.update(y)    # modifies z with y's keys and values & returns None
        return z
    

    ve

    z = merge_two_dicts(x, y)
    

açıklama

İki dicts varsa ve özgün dicts değiştirmeden yeni bir dict onları birleştirmek istediğini farz edelim:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

İstenen sonuç (Yeni sözlük elde etmektir zdeğerler birleşti ile) ve ikinci Dict değerlerini ilk gelenler üzerine yazarak.

>>> z
{'a': 1, 'b': 3, 'c': 4}

Önerilen bunun için yeni bir sözdizimi, PEP 448 ve Python 3.5 itibariyle mevcut olduğu

z = {**x, **y}

Ve gerçekten tek ifadesidir. Şimdi sıra uygulanan gösteriyor PEP 478, 3.5 için sürüm programına ve yolunda yaptığı artık gelmiştir Python Yenilikler 3.5 belgenin.

birçok kuruluş Python 2 hala beri Ancak, bir geriye doğru uyumlu bir şekilde bunu yapmak isteyebilir. Python 2 ve Python 3.0-3.4 mevcut klasik Pythonictir şekilde, iki aşamalı bir süreç olarak bu yapmaktır:

z = x.copy()
z.update(y) # which returns None since it mutates z

Her iki yaklaşımda da yikinci gelecek ve onun değerlerini yerini alacak xböylece 'in değerlerine 'b'işaret eder 3bizim nihai sonuçta.

Henüz Python 3.5 üzerinde, ama bir istiyorum tek bir ifade

Eğer Python 3.5 üzerinde henüz değilseniz veya geriye dönük olarak uyumlu kod yazmak gerekir ve bir de bunu istiyor Tek bir ifadede doğru yaklaşım bir işlev koymak iken, etkili ve verimli:

def merge_two_dicts(x, y):
    """Given two dicts, merge them into a new dict as a shallow copy."""
    z = x.copy()
    z.update(y)
    return z

ve sonra tek bir ifade vardır:

z = merge_two_dicts(x, y)

Ayrıca çok sayıda sıfırdan, dicts belirsiz bir sayıda birleştirme için bir işlev yapabilir:

def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

Bu fonksiyon tüm dicts için Python 2. ve 3. çalışacaktır. örneğin dicts verilen aetmek g:

z = merge_dicts(a, b, c, d, e, f, g) 

ve anahtar değer çiftleri gdicts göre öncelikli olacağını ahiç fbenzeri, ve.

Diğer Cevaplar EleĢtirileri

Eğer eskiden kabul edilen yanıt gördüklerinizi kullanmayın:

z = dict(x.items() + y.items())

Python 2'de, sen, her dict için hafızada iki listeleri oluşturmak araya ilk iki uzunluğuna eşit uzunlukta bellekte üçüncü liste oluşturmak ve sonra dicti oluşturmak üzere üç listeleri atın. Python 3, bu başarısız olur iki ekliyoruz çünkü dict_itemsaraya nesneleri değil iki liste -

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

ve açıkça örneğin listeleri gibi bunları oluşturmak gerekir z = dict(list(x.items()) + list(y.items())). Bu kaynaklar ve hesaplama gücü kaybıdır.

Benzer şekilde, bir birlik alma items()(Python 3 viewitems()değerleri unhashable nesneler (listeleri gibi örneğin) olduğunda Python 2.7) de başarısız olur. Değerleriniz, hashable bile setleri anlamsal sırasız olduğundan, davranış önceliği açısından tanımlanmamış. Yani bunu yapmayın:

>>> c = dict(a.items() | b.items())

Bu örnek değerler unhashable çocuklara ne oluyor gösterir:

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

İşte y öncelik olmalıdır bir örnek, ancak bunun yerine x gelen değer setlerinin keyfi emri nedeniyle korunur:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

Başka sen kullanmamalısınız kesmek:

z = dict(x, **y)

Bu kullanır dictyapıcı ve (bizim iki aşamalı bir süreçte bile biraz daha-so) verimli çok hızlı ve hafıza ama tam olarak ne oluyor burada bilmedikçe (yani, ikinci dict dict anahtar kelime argümanlar olarak geçirildiği yapıcı), onu okumak için amaçlanan kullanım zor değil, ve bu yüzden Pythonic değil.

İşte edilen kullanım örneği django çözüm getirilecek .

Dicts hashable tuşları (örn frozensets veya dizilerini) almaya yöneliktir, ancak tuşlar dizeleri olmadığında bu yöntem Python 3'te başarısız olur.

>>> c = dict(a, **b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

Gönderen posta listesine , Guido van Rossum, dilin yaratıcısı yazdı:

Ben dicti ilan ile iyiyim ({}, ** {1: 3}) yasadışı, sonuçta bu yana ** mekanizmasının kötüye kullanmasıdır.

ve

Görünüşe dict (x, ** y) için "serin hack" "çağrı x.update (y) ve x dönüş" olarak etrafında oluyor. Şahsen ben serin olmadığı kadar daha aşağılık bulabilirsiniz.

Anladığım kadarıyla (yanı sıra anlaşılmasıdır dilin yaratıcısı yönelik kullanım olduğunu) dict(**y)okunabilirliği amaçlar için, örneğin dicts yaratmak içindir:

dict(a=1, b=10, c=11)

yerine

{'a': 1, 'b': 10, 'c': 11}

Yorumlara Tepki

Guido söylediklerini rağmen dict(x, **y)btw dict şartname ile uyumludur. Python 2 ve 3 dize anahtarları için bu sadece çalışır doğrudan nasıl anahtar kelime parametre çalışması sonucu değil, dict kısa geliyorsun olması için çalışır. Ne de aslında ** anahtar kelimeler olarak dicts geçmek hassas tasarlanmış, bu yerde mekanizmanın kötüye ** operatörü kullanıyor.

Tuşları olmayan dizeleri olduğunda Yine, 3 için çalışmaz. Örtülü çağrı sözleşme kullanıcılar sadece dizeleri anahtar kelime argümanlar geçmelidir iken ad, sıradan dicts almasıdır. Diğer tüm callables bunu uygulamıştır. dictPython 2'de bu tutarlılık kırdı:

>>> foo(**{('a', 'b'): None})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() keywords must be strings
>>> dict(**{('a', 'b'): None})
{('a', 'b'): None}

Bu tutarsızlık kötü Python (PYPY, Jython, IronPython) diğer uygulamaları verildi. bu kullanım bir kesme değişiklik olabilir Böylece bu Python 3 giderilmiştir.

Bunun kasıtlı sadece bir dilin bir sürümünde veya belirli keyfi kısıtlamalar verilen tek eser çalıştığını kod yazmak için zararlı beceriksizliği olduğunu size gönderin.

Başka bir yorum:

dict(x.items() + y.items()) Hala Python 2. Okunabilirlik sayımları için en okunabilir bir çözümdür.

Benim yanıtı: merge_two_dicts(x, y)Biz okunabilirlik konusunda aslında endişeleriniz varsa aslında, bana çok daha net görünüyor. Python 2 giderek kullanımdan kaldırıldı Ve o, ileriye uyumlu değildir.

Yeterli performansı Ama Doğru Reklam-hocs

Bu yaklaşımlar yeterli performansı, ancak doğru davranışı sağlayacaktır. Bunlar olacak daha az ölçülebilir daha copyve updateya da daha yüksek bir soyutlama seviyesinde her bir anahtar değeri çifti boyunca yineleme, ancak, çünkü açma yeni yapmak öncelik sırasını (ikinci dicts önceliğe sahip) saygı

Ayrıca dict anlama içine elle dicts zincir edebilirsiniz:

{k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7

veya piton 2.6 (ve belki de en erken 2.4 olarak jeneratör ifadeler tanıştırılınca):

dict((k, v) for d in dicts for k, v in d.items())

itertools.chain olacak doğru sırayla anahtar değeri çifti boyunca yineleyicileri zincir:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

Performans analizi

Ben sadece doğru davranmaya bilinen kullanımların performans analizini yapacağım.

import timeit

Aşağıdaki Ubuntu 14.04 yapılır

Python 2.7 (sistem Python):

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(), y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

Python 3.5 olarak (PPA deadsnakes):

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

Sözlükler üzerinde Kaynakları

Cevap 10/11/2014 saat 20:11
kaynak kullanıcı

oy
41

Python 3.5 (PEP 448) güzel bir sözdizimi seçeneği sağlar:

x = {'a': 1, 'b': 1}
y = {'a': 2, 'c': 2}
final = {**x, **y} 
final
# {'a': 2, 'b': 1, 'c': 2}

Ya da

final = {'a': 1, 'b': 1, **x, **y}
Cevap 26/02/2015 saat 19:27
kaynak kullanıcı

oy
3
a = {1: 2, 3: 4, 5: 6}
b = {7:8, 1:2}
combined = dict(a.items() + b.items())
print combined
Cevap 20/03/2015 saat 22:06
kaynak kullanıcı

oy
5

Bu, tek bir dict anlayışı ile yapılabilir:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> { key: y[key] if key in y else x[key]
      for key in set(x) + set(y)
    }

Bence 'tek ifadesi' bölümü için en iyi yanıtı hiçbir ekstra fonksiyonlar ihtiyacı vardı ve bunu kısa gibidir.

Cevap 17/07/2015 saat 13:47
kaynak kullanıcı

oy
13

düzeni (ikincisi dicts önceliğe sahiptir) korur itertools kullanılarak basit çözüm

import itertools as it
merge = lambda *args: dict(it.chain.from_iterable(it.imap(dict.iteritems, args)))

Ve kullanımı:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> merge(x, y)
{'a': 1, 'b': 10, 'c': 11}

>>> z = {'c': 3, 'd': 4}
>>> merge(x, y, z)
{'a': 1, 'b': 10, 'c': 3, 'd': 4}
Cevap 04/08/2015 saat 13:54
kaynak kullanıcı

oy
5
from collections import Counter
dict1 = {'a':1, 'b': 2}
dict2 = {'b':10, 'c': 11}
result = dict(Counter(dict1) + Counter(dict2))

Bu probleminizi çözmeli.

Cevap 30/11/2015 saat 11:04
kaynak kullanıcı

oy
16

Pythonic olun. Bir kullan anlama :

z={i:d[i] for d in [x,y] for i in d}

>>> print z
{'a': 1, 'c': 11, 'b': 10}
Cevap 20/01/2016 saat 09:46
kaynak kullanıcı

oy
6

(Python2.7 için * Yalnızca; daha basit Python3 için çözümler * vardır.)

Standart bir kütüphane modülü ithal hoşlanmıyorsunuz değilseniz, yapabileceğiniz

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

( or aBit lambdaçünkü gerekli dict.updatezaman döner Nonebaşarısına.)

Cevap 28/03/2016 saat 12:13
kaynak kullanıcı

oy
4

Bu gerçekten soruları ( "bir liner") özelliklerini uymuyor biliyorum ama beri hiçbiri sürü ve cevapları sürü performans sorunu ele ederken cevapların yukarıda bu yönde gitti, ben düşüncelerimi katkıda bulunmalıdır hissetti.

Kullanım durumuna bağlı olarak, verilen giriş sözlükleri bir "gerçek" Birleştirilen sözlüğü oluşturmak için gerekli olmayabilir. Bir görüş , bu birçok durumda yeterli olabilir yapar davranan bir nesne yani gibi tamamen bilgisayar almadan yapacağı birleştirilmiş Sözlük. Birleştirilmiş sözlüğün Tembel versiyonu tabiri caizse.

Python, bu oldukça basit ve Yazımın sonunda gösterilen kod ile yapılabilir. Bu göz önüne alındığında, orijinal sorunun cevabı şöyle olacaktır:

z = MergeDict(x, y)

Bu yeni bir nesne kullanırken, birleştirilmiş sözlük gibi davranacaktır ama orijinal sözlükleri kalması sağlanabiliyor sabit oluşturma süresi ve sabit bellek ayak izi olacaktır. Bunu oluşturma önerilen diğer çözümlerde çok daha ucuzdur.

Eğer bir sonuç çok kullanırsanız gerçek birleştirilmiş Sözlük hızlı çözüm olurdu oluştururken nerede Tabii, o zaman bir noktada limiti ulaşacaktır. Dediğim gibi, bu kullanım durumuna göre değişir.

Hiç birleştirilmiş bir gerçek olmasını tercih ediyorum hissetti olursa dict, o zaman çağırarak dict(z)onu üretecektir (ama tabii diğer çözümlere yol daha masraflı, bu nedenle bu söz sadece değer).

Ayrıca kopya üzerinde yazma sözlüğe bir tür yapmak için bu sınıfı kullanabilirsiniz:

a = { 'x': 3, 'y': 4 }
b = MergeDict(a)  # we merge just one dict
b['x'] = 5
print b  # will print {'x': 5, 'y': 4}
print a  # will print {'y': 4, 'x': 3}

İşte düz ileri kodu MergeDict:

class MergeDict(object):
  def __init__(self, *originals):
    self.originals = ({},) + originals[::-1]  # reversed

  def __getitem__(self, key):
    for original in self.originals:
      try:
        return original[key]
      except KeyError:
        pass
    raise KeyError(key)

  def __setitem__(self, key, value):
    self.originals[0][key] = value

  def __iter__(self):
    return iter(self.keys())

  def __repr__(self):
    return '%s(%s)' % (
      self.__class__.__name__,
      ', '.join(repr(original)
          for original in reversed(self.originals)))

  def __str__(self):
    return '{%s}' % ', '.join(
        '%r: %r' % i for i in self.iteritems())

  def iteritems(self):
    found = set()
    for original in self.originals:
      for k, v in original.iteritems():
        if k not in found:
          yield k, v
          found.add(k)

  def items(self):
    return list(self.iteritems())

  def keys(self):
    return list(k for k, _ in self.iteritems())

  def values(self):
    return list(v for _, v in self.iteritems())
Cevap 18/05/2016 saat 14:57
kaynak kullanıcı

oy
9

Python 2 için:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()+y.items())
print(z)

Python 3 için:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()|y.items())
print(z)

Bu çıktıyı verir:{'a': 1, 'c': 11, 'b': 10}

Cevap 31/08/2016 saat 12:53
kaynak kullanıcı

oy
6

Python 3.5 size unpack kullanabilirsiniz **Yeni sözlük oluşturmak için. Bu yöntem hiçbir geçmiş cevaplar gösterdi edilmiştir. Ayrıca, kullanımı daha iyidir {}yerine dict(). Çünkü {}bir piton değişmez ve dict()bir işlev çağrısını içerir.

dict1 = {'a':1}
dict2 = {'b':2}
new_dict = {**dict1, **dict2}
>>>new_dict
{'a':1, 'a':2}
Cevap 27/09/2016 saat 23:33
kaynak kullanıcı

oy
6

Sen kullanabilirsiniz toolz.merge([x, y])bunun için.

Cevap 18/11/2016 saat 10:53
kaynak kullanıcı

oy
9

piton 3'te:

import collections
a = {1: 1, 2: 2}
b = {2: 3, 3: 4}
c = {3: 5}

r = dict(collections.ChainMap(a, b, c))
print(r)

Dışarı:

{1: 1, 2: 2, 3: 4}

Dokümanlar: https://docs.python.org/3/library/collections.html#collections.ChainMap :

Cevap 24/05/2017 saat 06:24
kaynak kullanıcı

oy
1

Sorusu etiketlendiği python-3xancak, görece yeni bir ek olduğunu dikkate alarak ve oy En olduğu, bir Python 2.x çözeltisi ile yoğun cevabı fırsatları kabul, ben cesaret Python 2.x bir tahriş edici özelliğini çeken bir tek astar eklemek liste anlama, yani adı sızdırıyor ...

$ python2
Python 2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> [z.update(d) for z in [{}] for d in (x, y)]
[None, None]
>>> z
{'a': 1, 'c': 11, 'b': 10}
>>> ...

Yukarıda Python 3 herhangi bir sürümü üzerinde bir daha çalışmaz söylemek mutluyum.

Cevap 30/05/2017 saat 11:28
kaynak kullanıcı

oy
2

Eğer mutasyona sakıncası yoksa x,

x.update(y) or x

Performant, okunabilir, basit. Sen biliyor update() hep döndüren Nonebir yanlış değer olan. Bu yüzden her zaman için değerlendirecektir x.

Standart kütüphanede mutasyona yöntemleri gibi update, dönüş NoneKongre tarafından, bu nedenle bu hüner de o üzerinde çalışacak.

Bu kongre uymayan bir kitaplığı kullanarak ediyorsanız, yerine, o tek bir ifade yapmak için bir kayıt düzeni ekran ve dizin kullanabilirsiniz or, ama o kadar okunabilir değil.

(x.update(y), x)[-1]

Eğer yoksa xhenüz bir değişkene kullanabileceğiniz lambdabir atama deyimi kullanmadan bir yerel yapmak. Bu kullanarak tutarındaki lambdabir şekilde let ifadesi ortak bir fonksiyonel dilde tekniği, daha çok unpythonic olduğunu.

(lambda x: x.update(y) or x)({'a':1, 'b': 2})

Eğer bir kopyasını istiyorsanız, söz PEP 448 en iyisidir {**x, **y}. Bu mevcut değil Ama eğer, let burada da işler.

(lambda z: z.update(y) or z)(x.copy())
Cevap 22/09/2017 saat 01:57
kaynak kullanıcı

oy
-3

X = { "a": 1}

y = { "B": 2}

x.update (y)

print x # { 'a': 1, 'b': 2}

Cevap 20/11/2017 saat 09:53
kaynak kullanıcı

oy
-4
dictionaries = [{'body': 'text'},
{'correctAnswer': 'text'},
{'ans': 'text'},
{'ans': 'text'}]

final_dictionary = {}
for dictionary in dictionaries:
    for key in dictionary:
        final_dictionary[key] = dictionary[key]

print(final_dictionary)

Eğer Python için çok yeni gibi geliyor, bu yüzden öneririm çözüm sadece for-döngüler biliyor ve bir sözlük tuşları üzerinde yineleme birine en okunabilir olduğunu düşünüyorum yukarıda biridir. aşağıdaki gibi sözde kodu:

for each of the dictionaries in the list: 
    add each of the key-value pairs in that dictionary to our final dictionary.
Cevap 04/12/2017 saat 20:56
kaynak kullanıcı

oy
1

Kod pasajı - son

piton 3.6. *

d1 = {"a":1,"b":2,"c":3}
d2 = {"d":4,"e":5,"f":6}
d3 = {"g":7,"h":8,"j":9}
d4 = {'wtf':'yes'}

d1a = {"a":1,"b":2,"c":3}
d1b = {"a":2,"b":3,"c":4}
d1c = {"a":3,"b":4,"c":5}
d1d = {"a":"wtf"}

def dics_combine(*dics):
    dic_out = {}
    for d in dics:
        if isinstance(d, dict):
            dic_out = {**dic_out, **d}
        else:
            pass
    return dic_out

inp = (d1,d2,d3,d4)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics))

inp = (d1a,d1b,d1c,d1d)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics))

inp = (d1d,d1c,d1b,d1a)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics)))

IN-SİPARİŞ ({ 'a': 1, 'B': 2 'c': 3}, { 'd': 4, 'e': 5, 'f': 6}, { 'g': 7, 'h': 8, 'j': 9}, { 'wtf': 'evet'})

OUT: { 'a': 1, 'b': 2 'c': 3, 'd': 4, 'e': 5, 'f': 6 'g': 7, 'h': 8 , 'j': 9, 'wtf': 'evet'}

IN-SİPARİŞ ({ 'a': 1, 'B': 2 'c': 3}, { 'a': 2 'b', 3, 'c': 4}, { 'a': 3, 'b': 4, 'c': 5}, { 'a': 'wtf'})

OUT: { 'a': 'wtf', 'b': 4, 'c': 5}

IN-SİPARİŞ ({ 'a': 'wtf'}, { 'a': 3, 'b': 4, 'c': 5}, { 'a': 2 'b', 3, 'C ': 4}, {' a ': 1, 'b': 2 ' c': 3})

OUT: { 'a': 1, 'b': 2 'c': 3}

Cevap 07/02/2018 saat 20:05
kaynak kullanıcı

oy
0

Ben bir tek satır stringify yaklaşımla kabul cevabım zaman yenebilirim merak ettim:

hepsi tek bir astar - - bütün üreten doğru cevaplar - Ben 5 yöntemler, hiçbiri daha önce bahsedildiği denedim ve yakın gelemedi.

Öyleyse ... sana zahmetten kurtarıp belki merakı yerine getirmek için:

import json
import yaml
import time
from ast import literal_eval as literal

def merge_two_dicts(x, y):
    z = x.copy()   # start with x's keys and values
    z.update(y)    # modifies z with y's keys and values & returns None
    return z

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

start = time.time()
for i in range(10000):
    z = yaml.load((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify yaml')

start = time.time()
for i in range(10000):
    z = literal((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify literal')

start = time.time()
for i in range(10000):
    z = eval((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify eval')

start = time.time()
for i in range(10000):
    z = {k:int(v) for k,v in (dict(zip(
            ((str(x)+str(y))
            .replace('}',' ')
            .replace('{',' ')
            .replace(':',' ')
            .replace(',',' ')
            .replace("'",'')
            .strip()
            .split('  '))[::2], 
            ((str(x)+str(y))
            .replace('}',' ')
            .replace('{',' ').replace(':',' ')
            .replace(',',' ')
            .replace("'",'')
            .strip()
            .split('  '))[1::2]
             ))).items()}
elapsed = (time.time()-start)
print (elapsed, z, 'stringify replace')

start = time.time()
for i in range(10000):
    z = json.loads(str((str(x)+str(y)).replace('}{',', ').replace("'",'"')))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify json')

start = time.time()
for i in range(10000):
    z = merge_two_dicts(x, y)
elapsed = (time.time()-start)
print (elapsed, z, 'accepted')

Sonuçlar:

7.693928956985474 {'c': 11, 'b': 10, 'a': 1} stringify yaml
0.29134678840637207 {'c': 11, 'b': 10, 'a': 1} stringify literal
0.2208399772644043 {'c': 11, 'b': 10, 'a': 1} stringify eval
0.1106564998626709 {'c': 11, 'b': 10, 'a': 1} stringify replace
0.07989692687988281 {'c': 11, 'b': 10, 'a': 1} stringify json
0.005082368850708008 {'c': 11, 'b': 10, 'a': 1} accepted

ne bundan öğrendin olmasıdır jsonyaklaşım en hızlı yolu (teşebbüs olanların) string-of-sözlükten bir sözlük döndürmektir; Kullandığım normal yöntem olarak kabul ne (zamanın yaklaşık 1/4) çok daha hızlı ast. Ayrıca, öğrendik yamlyaklaşım ne pahasına olursa olsun kaçınılmalıdır.

Evet, bu yüzden olumsuz af için downvote etmeyiniz en iyi / doğru yol olmadığını olsun, sıfır ve gayet iyi. o değil mi, hangi hızlıydı merak ettim; Öyle bunu kanıtlamak için yayınlanmıştır.

Cevap 22/03/2018 saat 02:08
kaynak kullanıcı

oy
0

Bu kullanarak sözlükleri birleştirir Python 3.5 veya daha fazlası için bir ifadesidir reduce:

>>> from functools import reduce
>>> l = [{'a': 1}, {'b': 2}, {'a': 100, 'c': 3}]
>>> reduce(lambda x, y: {**x, **y}, l, {})
{'a': 100, 'b': 2, 'c': 3}

Not: Bu sözlük listesi boşsa veya sadece bir eleman içerse dahi çalışır.

Cevap 15/04/2018 saat 22:02
kaynak kullanıcı

oy
0

Nerede Kodunuzdaki sorun nedir?

Python, sözlük anahtarları benzersiz ve değişmez nesnelerdir anahtar-değer eşleştirilmiş öğelerin bir sırasız koleksiyonu olarak tanımlanmaktadır.

update()Yöntem yani arama sözlüğü nesneyi güncelleştirir xsözlük nesne ie geçen içeriğiyle y.

çağıran nesnesindeki tüm çoğaltılmış anahtarı bulur, o zaman değeri nesne geçen eşleşen anahtarına karşılık gelen değerini geçersiz kılar.

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

Yani alacak {'a': 1, 'b': 10, 'c': 11}alma yerine{'a': 1, 'b': 10, 'c': 11, 'b': 2}

çözmek için sözlük anlama kullanın

profesyonel yolu mevcut sözlükleri veya başka yineleyici nesneleri kullanarak sözlükleri oluşturmak için.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>>
>>> my_dicts = (x, y);  # Gathering all dictionaries in a tuple/list
>>> z = {key: value for my_dict in my_dicts for key, value in my_dict.iteritems()}; # Single line of code that creates new dictionary object from existing dictionaries
>>> z
{'a': 1, 'c': 11, 'b': 10}

Referanslar

https://www.datacamp.com/community/tutorials/python-dictionary-comprehension

Teşekkürler.

Cevap 07/05/2018 saat 05:53
kaynak kullanıcı

oy
0

Benim çirkin bir astarları burada sadece gerekli olduğunu düşünüyorum.

z = next(z.update(y) or z for z in [x.copy()])
# or
z = (lambda z: z.update(y) or z)(x.copy())
  1. Dicts birleştirilir.
  2. Tek ifade.
  3. Hiç kullanmaya kalkma.
Cevap 11/05/2018 saat 09:00
kaynak kullanıcı

oy
4

python2 olarak

dict(mydict, **other)

veya

In [11]: dict({1:2}.items() + {2:3}.items() + {1:5}.items() )
Out[11]: {1: 5, 2: 3}

python3

{ **mydict, **otherdict}
Cevap 28/06/2018 saat 11:33
kaynak kullanıcı

oy
1

Yeni bir seçenek olacaktır ne zaman (Python 3.8 bültenleri , 20 Ekim 2019 için planlanan ), sayesinde PEP 572: Atama İfadelerin . Yeni atama ifadesi operatörü :=size sonucunu atamak için izin verir copyve yine aramak için kullanabiliriz update, iki ifadeleri yerine, birleşik kodu tek bir ifade bırakarak değişen:

newdict = dict1.copy()
newdict.update(dict2)

için:

(newdict := dict1.copy()).update(dict2)

her şekilde aynı davranırken. Ayrıca çıkan dönmek gerekirse dict(Eğer dönen bir ifadenin istedi dictyukarıda oluşturur ve atar newdictsen olduğu gibi bir işleve bir argüman iletilmesi kullanmayın böylece, ama bunu dönmez, a la myfunc((newdict := dict1.copy()).update(dict2))) , o zaman sadece ekleyin or newdict(çünkü sonuna kadar updategetiri Nonedaha sonra değerlendirmek ve dönecektir, falsy olan newdictifadenin sonucu olarak):

(newdict := dict1.copy()).update(dict2) or newdict

Önemli uyarı: Genel olarak, ben lehine bu yaklaşımı önermem:

newdict = {**dict1, **dict2}

Açma yaklaşım (yaklaşık ilk etapta açma genelleştirilmiş bilir hangi birisine nettir sen gerektiğini , geçici olduğunu hemen geçirilir inşa sırasında bu yüzden çok daha özlü var (hiç bir sonuç için bir ad gerektirmez) fonksiyon veya dahil list/ tuple) literal veya benzeri ve neredeyse kesinlikle daha hızlı, hem de (hemen hemen eşit) CPython üzerinde olmak:

newdict = {}
newdict.update(dict1)
newdict.update(dict2)

ancak beton kullanarak, Cı katmanında yapılır dictAPI, yani dinamik bir yöntem arama / bağlayıcı veya işlev çağrısı gönderme yükü burada (katılır (newdict := dict1.copy()).update(dict2)dinamik arama ile, farklı aşamalarda tutmadan, davranış orijinal iki astara kaçınılmaz aynıdır / yöntemleri bağlama / çağırma.

Üç birleştirme gibi, aynı zamanda daha genişletilebilir var dicts açıktır:

 newdict = {**dict1, **dict2, **dict3}

nerede böyle ölçek olmayacak atama ifadeler kullanarak; En yakın olurdunuz alabilir:

 (newdict := dict1.copy()).update(dict2), newdict.update(dict3)

veya geçici başlığın olmadan Nones, ancak her birinin truthiness testi ile Nonesonuç:

 (newdict := dict1.copy()).update(dict2) or newdict.update(dict3)

bunlardan herhangi biri tabii ki çok daha çirkin ve ayrıca yetersizliklere içerir (bir boşa geçici tuplebir Nonevirgül ayrılması, ya da her bir anlamsız truthiness test s update'in Nonedönüş orayrılması).

atama ifadesi yaklaşımına tek gerçek avantaj olursa oluşur:

  1. Her iki ele ihtiyaç jenerik koduna sahip sets ve dicts (her ikisi de destekleyecek copyve updatekod bunu beklediğiniz kabaca çalışır, böylece)
  2. Sen keyfi dict benzeri nesneleri almayı bekliyoruz , sadece dictkendisini, ve türünü ve sol tarafta semantik korumalıdır (yerine bir ova ile biten daha dict). İken myspecialdict({**speciala, **specialb})işe yarayabilecek, bu ekstra geçici yer alacağı dictve eğer myspecialdictözelliklere sahiptir düz dict(örneğin düzenli korumak olamaz dictler artık önemli son görünüme dayalı bir anahtarın ilk görünüm dayalı düzeni korumak ve değeri; isteyebileceğiniz dayalı düzeni koruyan bir son yani değeri de sonuna kadar taşır güncellenmesi bir anahtar ortaya), sonra semantik yanlış olur. Atama ifadesi sürümü (muhtemelen uygun davranmaya aşırı yüklü) adlı yöntemler kullandığından asla oluşturur dict(sürece hiç dict1zaten oldu dictherhangi geçiciri kaçınarak bu arada orijinal türünü (ve orijinal türünün anlambilim) koruyarak).
Cevap 28/02/2019 saat 15:16
kaynak kullanıcı

oy
0

Ben aşağıdakileri yapmanız gerektiğini söyleyebilirim:

z = dict(x.items() + y.items())
Cevap 19/03/2019 saat 04:40
kaynak kullanıcı

oy
0

Hızlı bir çözüm olacaktır:

z4 = x.copy().update(y)
Cevap 26/03/2019 saat 10:03
kaynak kullanıcı

oy
0

Python 3 için:

from collections import ChainMap
a = {"a": 1, "b":2}
b = {"c":5, "d":8}
dict(ChainMap(a,b))  # {"a":1, "b":2, "c":5, "d":8}

Her iki sözlüklerde aynı anahtarı varsa, ChanMap ilk anahtarın değeri kullanın ve ikinci anahtarın değeri yok sayar olacaktır. Şerefe!

Cevap 31/05/2019 saat 19:10
kaynak kullanıcı

oy
0

Bunu yapmak için bir işlev kullanabilirsiniz:

def append(d1, d2):
    d1.update(d2)
    return d1

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = append(x, y)
print(z) #{'a': 1, 'b': 10, 'c': 11}
Cevap 19/07/2019 saat 22:44
kaynak kullanıcı

oy
0
 d1 = {'a': 10, 'b': 20}
 d2 = {'c': 30, 'd': 40, 'b': 50}
 l = d1.copy()
 s.update(d2)
 print(s)

çıktı:

{'a': 10, 'b': 50, 'c': 30, 'd': 4
Cevap 14/09/2019 saat 18:33
kaynak kullanıcı

oy
0

Bazı yollar kodlarının birkaç satır ile herhangi bir piton modülleri (bağımlılık yok) kullanmadan bunu çözmek için.

TÜM Python sürümleri (Lambda kullanılarak):

merge_dicts = lambda old, new: old.update(new) or old

Python Sürüm> = 3.5:

def merge_dicts(old, new):
    return {**old, **new} 

Yaşlı Python Versiyon:

def merge_dicts(old, new):
    merged = old.copy()
    merged.update(new)
    return merged

yeni değerlerle eski değerleri silerken Bu örnek, eski ve yeni birleştirilecek.

KULLANIM:

old = {'name': 'Kevin', 'phone_number': '+33 12 34 45 67'}
new = {'name': 'Kevin', 'phone_number': '+33 88 88 88 88'}

print(merge_dicts(old, new))

ÇIKTI:

{'name': 'Kevin', 'phone_number': '+33 88 88 88 88'}

Eğer katları ile uğraşmak zorunda IF sözlükler dizisini kullanarak aşağıdaki herhangi bir veri bir örnek yaklaşımını kaybetmeden, yeni eski sürümünden birleşti:

TÜM Python sürümleri:

def merge_dicts(old, news):
    merged = old.copy()
    for new in news:
        merged.update(new)
    return merged

KULLANIM:

old = {'name': 'Kevin', 'phone_number': '+33 12 34 45 67'}
new_01 = {'name': 'Kevin', 'phone_number': '+33 77 77 77 77', 'age': 28}
new_02 = {'name': 'SabK', 'phone_number': '+33 88 88 88 89'}
new_03 = {'phone_number': '+33 99 99 99 99'}

print(merge_dicts(old, [new_01, new_02, new_03]))

ÇIKTI:

{'phone_number': '+33 99 99 99 99', 'age': 28, 'name': 'SabK'}

Bu örnekte, yeni bir sözlük eski bir (ilk tartışma) oluşturulur ve daha sonra son bir dizinin birinci elemandan sırayla güncellenir (new_01> new_02> new_03)

sonunda, değerlerini güncelleyerek olacak sözlüğe tüm tüm verileri alacak değişiklik oldu olarak söyledi. Eğer sık ​​sık değişen veriler ile anlaşma olduğunda bu işlev gerçekten yararlı olabilir.

Cevap 06/12/2019 saat 23:46
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more