Как объединить два словаря в одном выражении?

У меня есть два словаря Python, и я хочу написать одно выражение, которое возвращает эти два словаря, объединенные. Метод update() был бы тем, что мне нужно, если бы он возвращал свой результат вместо того, чтобы модифицировать диктет на месте.

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

Как я могу получить этот последний объединенный dict в z, а не x?

(Для большей ясности, обработка конфликта dict.update() с последним выигрышем - это то, что я также ищу. )

вопрос задан 2.09.2008
Carl Meyer
57127 репутация

49 ответов


  • 0 рейтинг

    фрагмент кода - последние

    питон 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)))
    

    В ЗАКАЗЕ: ({'a': 1, 'b': 2, 'c': 3}, {'d': 4, 'e': 5, 'f': 6}, {'g' : 7, 'h': 8, 'j': 9}, {'wtf': 'yes'})

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

    В ЗАКАЗЕ: ({'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}

    В ЗАКАЗЕ: ({'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}

    ответ дан Goran B., с репутацией 317, 7.02.2018
  • 0 рейтинг

    Альтернатива:

    z = x.copy()
    z.update(y)
    
    ответ дан Matthew Schinckel, с репутацией 26442, 2.09.2008
  • 0 рейтинг

    В последующем ответе вы спросили об относительной эффективности этих двух альтернатив:

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

    На моей машине, по крайней мере (довольно обычный x86_64 под управлением Python 2. 5. 2) альтернатива z2 не только короче и проще, но и значительно быстрее. Вы можете убедиться в этом сами, используя модуль timeit, который поставляется с Python.

    Пример 1: идентичные словари, отображающие в себе 20 последовательных целых чисел:

    % 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
    

    z2 выигрывает с коэффициентом 3. 5 или около того. Различные словари, кажется, дают совершенно разные результаты, но z2 всегда кажется впереди. (Если вы получаете противоречивые результаты для того же теста для , попробуйте ввести -r с числом, превышающим значение по умолчанию 3. )

    Пример 2: неперекрывающиеся словари, отображающие 252 короткие строки в целые числа и наоборот:

    % 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 выигрывает примерно в 10 раз. Это довольно большая победа в моей книге!

    После сравнения этих двух я подумал, можно ли объяснить низкую производительность z1 накладными расходами на создание двух списков элементов, что, в свою очередь, заставило меня задуматься, может ли этот вариант работать лучше:

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

    Несколько быстрых тестов, e. г.

    % 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
    

    приводит меня к выводу, что z3 несколько быстрее, чем z1, но не так быстро, как z2. Определенно не стоит всего лишнего набора текста.

    В этом обсуждении все еще отсутствует что-то важное, а именно сравнение производительности этих альтернатив с «очевидным» способом объединения двух списков: с использованием метода update. Чтобы попытаться удержать вещи в равных условиях с выражениями, ни одно из которых не изменяет x или y, я собираюсь сделать копию x вместо ее изменения на месте следующим образом:

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

    Типичный результат:

    % 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
    

    Другими словами, z0 и z2, по-видимому, имеют практически одинаковую производительность. Как вы думаете, это может быть совпадением? Я не. , , ,

    Фактически, я бы зашел так далеко, что утверждал, что для чистого кода Python невозможно сделать что-то лучше этого. И если вы можете значительно улучшить работу модуля расширения C, я думаю, что пользователи Python вполне могут быть заинтересованы во включении вашего кода (или варианта вашего подхода) в ядро ​​Python. Python использует dict во многих местах; Оптимизация его операций - это большое дело.

    Вы также можете написать это как

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

    , как Тони, но (что неудивительно) разница в обозначениях оказывается не иметь какого-либо измеримого влияния на производительность. Используйте то, что подходит вам. Конечно, он абсолютно прав, указывая на то, что версия с двумя утверждениями гораздо легче понять.

    ответ дан zaphod, с репутацией 3087, 23.10.2008
  • 0 рейтинг

    Для этого можно использовать toolz.merge([x, y]) .

    ответ дан Mike Graham, с репутацией 48069, 18.11.2016
  • 0 рейтинг

    Злоупотребление, приводящее к решению с одним выражением для Ответ Мэтью :

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

    Вы сказали, что хотите одно выражение, поэтому я злоупотребил lambda, чтобы связать имя, и кортежами, чтобы переопределить ограничение в одно выражение для лямбды. Не стесняйтесь съеживаться.

    Конечно, вы можете сделать это, если не хотите копировать его:

    >>> x = {'a':1, 'b': 2}
    >>> y = {'b':10, 'c': 11}
    >>> z = (x.update(y), x)[1]
    >>> z
    {'a': 1, 'b': 10, 'c': 11}
    
    ответ дан Claudiu, с репутацией 122117, 7.08.2013
  • 0 рейтинг

    У меня есть решение, которое не указано здесь (Человек, которого я люблю Python) :-)

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

    Это не обновит x так же как y. Спектакль? Я не думаю, что это будет ужасно медленно :-)

    ПРИМЕЧАНИЕ. Предполагается, что это операция или операция, а не операция. Отредактировано, чтобы исправить код.

    ответ дан thiruvenkadam, с репутацией 2024, 5.12.2013
  • 0 рейтинг

    Простое решение с использованием itertools, сохраняющее порядок (последние имеют приоритет)

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

    И его использование:

    >>> 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}
    
    ответ дан reubano, с репутацией 2072, 4.08.2015
  • 0 рейтинг

    Лучшая версия, которую я мог бы подумать, не используя копию, была бы:

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

    Это быстрее, чем dict(x.items() + y.items()), но не так быстро, как n = copy(a); n.update(b), по крайней мере, на CPython. Эта версия также работает в Python 3, если вы измените iteritems() на items(), что автоматически выполняется инструментом 2to3.

    Лично мне эта версия больше всего нравится, потому что она достаточно хорошо описывает то, что я хочу, в едином функциональном синтаксисе. Единственная небольшая проблема заключается в том, что не очевидно, что значения от y имеют приоритет над значениями от x, но я не верю, что это трудно понять.

    ответ дан driax, с репутацией 1346, 14.10.2010
  • 0 рейтинг

    Это можно сделать с помощью единого понимания слова:

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

    На мой взгляд, лучший ответ для части с «одним выражением», так как никаких дополнительных функций не требуется, и она короткая.

    ответ дан RemcoGerlich, с репутацией 18577, 17.07.2015
  • 0 рейтинг

    В python2

    dict(mydict, **other)
    

    или

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

    python3

    { **mydict, **otherdict}
    
    ответ дан crook, с репутацией 646, 28.06.2018
  • 0 рейтинг

    Я знаю, что это не совсем соответствует специфике вопросов («один вкладыш»), но так как ни один из из приведенных выше ответов не пошел в этом направлении, в то время как множество и множество ответов касались проблемы производительности, я чувствовал, что должен внести свой вклад мысли.

    В зависимости от варианта использования может не потребоваться создание «реального» объединенного словаря из заданных входных словарей. Представление , которое делает это, может быть достаточным во многих случаях, т.е. е. объект, который действует , как , объединенный словарь не будет вычислять его полностью. Ленивая версия объединенного словаря, так сказать.

    В Python это довольно просто и может быть сделано с помощью кода, показанного в конце моего поста. Это, учитывая, ответ на оригинальный вопрос будет:

    z = MergeDict(x, y)
    

    При использовании этого нового объекта он будет вести себя как объединенный словарь, но у него будет постоянное время создания и постоянный объем памяти, а исходные словари останутся нетронутыми. Создание его намного дешевле, чем в других предлагаемых решениях.

    Конечно, если вы часто используете результат, то в какой-то момент вы достигнете предела, когда создание реального объединенного словаря было бы более быстрым решением. Как я уже сказал, это зависит от вашего варианта использования.

    Если вы когда-нибудь почувствовали, что предпочли бы иметь настоящее объединенное dict, то вызов dict(z) приведет к его получению (но, конечно, гораздо более дорогостоящему, чем другие решения, поэтому об этом просто стоит упомянуть).

    Вы также можете использовать этот класс для создания своего рода словаря для копирования при записи:

    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}
    

    Вот простой код 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())
    
    ответ дан Alfe, с репутацией 29807, 18.05.2016
  • 0 рейтинг

    Где проблема в вашем коде?

    В Python словарь определяется как неупорядоченная коллекция парных элементов со значением ключа, где ключи являются уникальными и неизменяемыми объектами.

    Метод update() обновляет вызывающий объект словаря i. е. x с содержимым передаваемого словаря объекта i. е. y .

    Если он найдет какой-либо дублированный ключ в вызывающем объекте, он заменит его значение значением, соответствующим согласованному ключу передаваемого объекта.

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

    Таким образом, вы получите {'a': 1, 'b': 10, 'c': 11} вместо получения {'a': 1, 'b': 10, 'c': 11, 'b': 2}

    Используйте словарное понимание, чтобы решить

    Профессиональный способ создания словарей с использованием существующих словарей или других объектов итераторов.

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

    Список литературы

    https: // www. datacamp. com / сообщество / учебники / python-словарь-понимание

    Спасибо.

    ответ дан hygull, с репутацией 2376, 7.05.2018
  • 0 рейтинг

    Как объединить два словаря Python в одно выражение?

    Для словарей x и y, z становится объединенным словарем со значениями от y, заменяющими значения из x.

    • В Python 3. 5 или больше:

      z = {**x, **y}
      w = {'foo': 'bar', 'baz': 'qux', **y}  # merge a dict with literal values
      
    • В Python 2, (или 3. 4 или ниже) напишите функцию:

      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
      

      и

      z = merge_two_dicts(x, y)
      

    Объяснение

    Скажем, у вас есть два диктата, и вы хотите объединить их в новый, не изменяя исходные:

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

    Желаемый результат - получить новый словарь (z) с объединенными значениями, а значения второго dict перезаписывают значения из первого.

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

    Новый синтаксис для этого, предложенный в PEP 448 и , доступен с Python 3. 5 ,

    z = {**x, **y}
    

    И это действительно одно выражение. Теперь он показывает, как реализовано в графике выпуска для 3. 5, PEP 478 , и теперь он вошел в Что нового в Python 3. 5 документ.

    Однако, так как многие организации все еще используют Python 2, вы можете сделать это обратно совместимым способом. Классически Pythonic способ, доступный в Python 2 и Python 3. 0-3. 4, это сделать в два этапа:

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

    В обоих подходах y будет вторым, и его значения заменят значения x, таким образом, 'b' будет указывать на 3 в нашем конечном результате.

    Еще не на Python 3. 5, но хотите одного выражения

    Если вы еще не на Python 3. 5, или вам нужно написать обратно совместимый код, и вы хотите, чтобы это было в одном выражении , наиболее эффективный и правильный подход - поместить его в функцию:

    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
    

    и тогда у вас есть одно выражение:

    z = merge_two_dicts(x, y)
    

    Вы также можете создать функцию для слияния неопределенного числа диктов от нуля до очень большого числа:

    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
    

    Эта функция будет работать в Python 2 и 3 для всех диктов. е. г. данные диктанты с a по g:

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

    и пары «ключ-значение» в g будут иметь приоритет над кодами с a по f и т. Д.

    Критика других ответов

    Не используйте то, что вы видите в ранее принятом ответе:

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

    В Python 2 вы создаете два списка в памяти для каждого dict, создаете третий список в памяти с длиной, равной длине первых двух вместе взятых, а затем отбрасываете все три списка для создания dict. В Python 3 это не удастся , потому что вы добавляете два объекта dict_items вместе, а не два списка -

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

    , и вам придется явно создавать их в виде списков, e. г. z = dict(list(x.items()) + list(y.items())). Это пустая трата ресурсов и вычислительной мощности.

    Точно так же, принимая объединение items() в Python 3 (viewitems() в Python 2. 7) также потерпит неудачу, когда значения являются недоступными объектами (например, списки). Даже если ваши значения могут быть хэшируемыми, , поскольку наборы семантически неупорядочены, поведение не определено в отношении приоритета. Так что не делайте этого:

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

    Этот пример демонстрирует, что происходит, когда значения не различимы:

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

    Вот пример, где у должен иметь приоритет, но вместо этого значение из x сохраняется из-за произвольного порядка наборов:

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

    Еще один хак, который вы не должны использовать:

    z = dict(x, **y)
    

    При этом используется конструктор dict, и он очень быстр и эффективен в использовании памяти (даже немного более, чем наш двухэтапный процесс), но если вы точно не знаете, что здесь происходит (то есть, второй dict передается в качестве аргументов ключевого слова для конструктор dict), его трудно читать, он не предназначен для использования и поэтому не является Pythonic.

    Вот пример использования , исправленного в django .

    Dicts предназначены для получения хеш-ключей (например, г. Frozensets или кортежи), но этот метод не работает в Python 3, когда ключи не являются строками.

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

    Из списка рассылки Гвидо ван Россум, создатель языка, написал:

    Я в порядке с объявляя dict ({}, ** {1: 3}) незаконным, так как в конце концов это злоупотребление ** механизм.

    и

    Очевидно, что dict (x, ** y) используется как «крутой хак» для «вызова». Икс. обновить (у) и вернуть х ". Лично я нахожу это более отвратительным, чем прохладно.

    Это мое понимание (а также понимание создателя языка ), что предполагаемое использование для dict(**y) предназначено для создания диктов в целях читабельности, e. г. :

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

    вместо

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

    Ответ на комментарий

    Несмотря на то, что говорит Гвидо, dict(x, **y) соответствует спецификации dict, которая, между прочим. работает как для Python 2 и 3. Тот факт, что это работает только для строковых ключей, является прямым следствием того, как работают параметры ключевых слов, а не коротким переходом к dict. Также использование оператора ** в этом месте не является злоупотреблением механизмом, фактически ** был разработан именно для передачи слов в качестве ключевых слов.

    Опять же, это не работает для 3, когда ключи не являются строками. Неявный контракт вызова заключается в том, что пространства имен принимают обычные диктовки, в то время как пользователи должны передавать только ключевые аргументы, которые являются строками. Все другие призывные силы принуждали его. dict нарушил эту согласованность в Python 2:

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

    Это несоответствие было плохим, учитывая другие реализации Python (Pypy, Jython, IronPython). Таким образом, это было исправлено в Python 3, так как это использование может быть серьезным изменением.

    Я утверждаю, что это злонамеренная некомпетентность - намеренно писать код, который работает только в одной версии языка или работает только при определенных произвольных ограничениях.

    Еще один комментарий:

    dict(x.items() + y.items()) - все еще самое читаемое решение для Python 2. Читаемость имеет значение.

    Мой ответ: merge_two_dicts(x, y) на самом деле кажется мне намного понятнее, если мы действительно обеспокоены читаемостью. И это не совместимо с форвардом, так как Python 2 все больше и больше устарел.

    Менее производительный, но правильный Ad-hocs

    Эти подходы менее производительны, но они обеспечат правильное поведение. Они будут на гораздо менее производительными , чем copy и update, или на новую распаковку, потому что они перебирают каждую пару ключ-значение на более высоком уровне абстракции, но они 3230269583 и соблюдают порядок приоритета (у последних диктов есть приоритет)

    Кроме того, вы можете связать слова вручную в их понимании:

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

    или в Python 2. 6 (и, возможно, уже 2. 4, когда были введены выражения генератора):

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

    itertools.chain будет связывать итераторы по парам ключ-значение в правильном порядке:

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

    Анализ производительности

    Я собираюсь провести анализ производительности только тех случаев, когда известно, что они работают правильно.

    import timeit
    

    Следующее сделано в Ubuntu 14. 04

    В Python 2. 7 (системный 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 (PPA):

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

    Ресурсы по словарям

      Мое объяснение реализации словаря Python , обновлено для 3. 6. Ответ о том, как добавить новые ключи в словарь Отображение двух списков в словарь
    • Официальный Python
    • документы по словарям Словарь даже могущественнее - разговор Брэндона Роудса на Pycon 2017 Современные словари Python, слияние великих идей - выступление Рэймонда Хеттингера на Pycon 2017

    ответ дан Aaron Hall, с репутацией 153756, 10.11.2014
  • 0 рейтинг
    x = {'a':1, 'b': 2}
    y = {'b':10, 'c': 11}
    z = dict(x.items() + y.items())
    print z
    

    Для элементов с ключами в обоих словарях ('b') вы можете контролировать, какой из них окажется в выводе, поместив этот последний.

    ответ дан Greg Hewgill, с репутацией 645957, 2.09.2008
  • 0 рейтинг

    В вашем случае вы можете сделать следующее:

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

    Это, как вы хотите, поместит окончательный dict в z и сделает значение ключа b надлежащим образом переопределенным значением второго (y):

    .
    >>> 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, это будет немного сложнее. Создать z:

    >>> z = dict(list(x.items()) + list(y.items()))
    >>> z
    {'a': 1, 'c': 11, 'b': 10}
    
    ответ дан Thomas Vander Stichele, с репутацией 28200, 2.09.2008
  • 0 рейтинг

    Это выражение для Python 3. 5 или более, которые объединяют словари, используя 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}
    

    Примечание: это работает, даже если список словаря пуст или содержит только один элемент.

    ответ дан Josh Bode, с репутацией 1895, 15.04.2018
  • 0 рейтинг

    Это так глупо, что .update ничего не возвращает.
    Я просто использую простую вспомогательную функцию для решения проблемы:

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

    Примеры:

    merge(dict1,dict2)
    merge(dict1,dict2,dict3)
    merge(dict1,dict2,dict3,dict4)
    merge({},dict1,dict2)  # this one returns a new copy
    
    ответ дан GetFree, с репутацией 21344, 2.03.2014
  • 0 рейтинг

    Это, вероятно, не будет популярным ответом, но вы почти наверняка не хотите этого делать. Если вы хотите копию, которая является слиянием, используйте копию (или deepcopy , в зависимости от того, что вы хотите), а затем обновите. Две строки кода гораздо более читабельны - более Pythonic - чем создание одной строки. предметы () +. Предметы(). Явное лучше, чем неявное.

    Кроме того, когда вы используете. items () (до Python 3. 0), вы создаете новый список, который содержит элементы из dict. Если ваши словари большие, то это очень много накладных расходов (два больших списка, которые будут выброшены, как только будет создан объединенный диктат). update () может работать более эффективно, потому что он может проходить через второй элемент dict элемент за элементом.

    В терминах времени :

    >>> 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 крошечное замедление между первыми двумя стоит его для удобочитаемости. Кроме того, ключевые аргументы для создания словаря были добавлены только в Python 2. 3, тогда как copy () и update () будут работать в более старых версиях.

    ответ дан Tony Meyer, с репутацией 7305, 8.09.2008
  • 0 рейтинг
    a = {1: 2, 3: 4, 5: 6}
    b = {7:8, 1:2}
    combined = dict(a.items() + b.items())
    print combined
    
    ответ дан Saksham Varma, с репутацией 1668, 21.03.2015
  • 0 рейтинг

    Мне было любопытно, смогу ли я побить время принятого ответа с помощью строкового подхода в одну строку:

    Я попробовал 5 методов, ни один из которых не упоминался ранее - все по одному вкладышу - все выдавали правильные ответы - и я не мог приблизиться.

    Итак. , , чтобы избавить вас от хлопот и, возможно, удовлетворить любопытство:

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

    результаты:

    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
    

    Из этого я узнал, что подход json является самым быстрым (из тех, кто пытался) возвратить словарь из словарной строки; намного быстрее (примерно 1/4 времени) того, что я считал нормальным методом с использованием ast. Я также узнал, что подхода yaml следует избегать любой ценой.

    Да, я понимаю, что это не лучший / правильный путь, поэтому, пожалуйста, не отрицайте отрицательное забвение, ноль - это просто отлично. Мне было любопытно, если бы это было быстрее, а это не так; Я отправил, чтобы доказать это так.

    ответ дан litepresence, с репутацией 1460, 22.03.2018
  • 0 рейтинг

    Хотя на вопрос уже отвечали несколько раз, это простое решение проблемы еще не было перечислено.

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

    Это так же быстро, как z0 и зло z2, упомянутое выше, но легко понять и изменить.

    ответ дан phobie, с репутацией 1486, 14.10.2011
  • 0 рейтинг

    В питоне 3:

    import collections
    a = {1: 1, 2: 2}
    b = {2: 3, 3: 4}
    c = {3: 5}
    
    r = dict(collections.ChainMap(a, b, c))
    print(r)
    

    Out:

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

    Документы: https: // документы. питон. орг / 3 / библиотека / коллекции. HTML # коллекции. ChainMap :

    ответ дан Skyduy, с репутацией 149, 24.05.2017
  • 0 рейтинг

    Приведенный ниже метод объединяет список переданных ему словарей. И это занимает меньше всего времени с точки зрения производительности.

    # Function to merge a list of dictionaries into one dict
    def dict_merger_fn(dict_list):
        z = dict_list[0].copy()
        for y in dict_list[1:]:
            z.update(y) # modifies z with y's keys and values & returns None
        return z
    

    Использование:

    merged_dict = dict_merger_fn([dict1,dict2,dict3...])
    
    ответ дан gourav sb, с репутацией 21, 10.09.2018
  • 0 рейтинг

    Объединение двух словарей ОП будет что-то вроде:

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

    В частности, объединение двух сущностей (x и y) содержит все элементы x и / или y. К сожалению, то, что просит ФП, не является профсоюзом, несмотря на название поста.

    Мой код ниже не является ни элегантным, ни однострочным, но я считаю, что это согласуется со смыслом объединения.

    Из примера ОП:

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

    Можно ли изменить какие-либо списки, но вышеприведенное будет работать, если словарь содержит списки (и вложенные списки) в качестве значений в любом словаре.

    ответ дан bassounds, с репутацией 49, 30.09.2014
  • 0 рейтинг
    >>> 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}
    
    ответ дан John La Rooy, с репутацией 201824, 13.11.2013
  • 0 рейтинг

    Я думаю, что мои уродливые однострочники просто необходимы здесь.

    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 объединяются.
    2. Одно выражение.
    3. Никогда не смей им пользоваться.
    ответ дан Tigran Saluev, с репутацией 2000, 11.05.2018
  • 0 рейтинг

    В python3 метод items больше не возвращает список , а представляет , который действует как набор. В этом случае вам нужно взять объединение множеств, так как объединение с + не будет работать:

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

    Для python3-подобного поведения в версии 2. 7, метод viewitems должен работать вместо items:

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

    Я предпочитаю эту запись в любом случае, так как кажется более естественным думать о ней как об операции объединения множеств, а не о конкатенации (как показывает заголовок).

    Редактировать:

    Еще пара баллов за питона 3. Во-первых, обратите внимание, что трюк dict(x, **y) не будет работать в Python 3, если ключи в y не являются строками.

    Кроме того, Chainmap Раймонда Хеттингера ответ довольно элегантен, поскольку он может принимать в качестве аргументов произвольное количество диктовок, но из документов выглядит так, как будто последовательно просматривает список всех диктов для каждого поиска:

    Поиски последовательно выполняют поиск соответствующих сопоставлений, пока не будет найден ключ.

    Это может замедлить вас, если у вас есть много поисков в вашем приложении:

    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
    

    Так что примерно на порядок медленнее для поисков. Я фанат Chainmap, но выглядит менее практичным там, где может быть много поисков.

    ответ дан beardc, с репутацией 7406, 9.10.2013
  • 0 рейтинг

    Для Python 2:

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

    Для Python 3:

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

    Дает вывод: {'a': 1, 'c': 11, 'b': 10}

    ответ дан Kalpesh Dusane, с репутацией 1009, 31.08.2016
  • 0 рейтинг

    В Python 3 вы можете использовать коллекций . ChainMap , который группирует несколько диктовок или других сопоставлений для создания единого обновляемого представления:

    >>> 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
    
    ответ дан Raymond Hettinger, с репутацией 125662, 28.04.2013
  • 0 рейтинг

    Проблема, с которой я столкнулся с решениями, перечисленными на сегодняшний день, состоит в том, что в объединенном словаре значение ключа "b" равно 10, но, по моему мнению, оно должно быть 12. В этом свете я представляю следующее:

    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
    

    Результаты:

    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}
    
    ответ дан upandacross, с репутацией 132, 3.12.2013
  • 0 рейтинг

    Два словаря

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

    n Словари

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

    sum имеет плохую производительность. См. https: // mathieularose. com / how-not-to-flatten-a-list-list-in-python /

    ответ дан Mathieu Larose, с репутацией 598, 17.10.2012
  • 0 рейтинг
    def dict_merge(a, b):
      c = a.copy()
      c.update(b)
      return c
    
    new = dict_merge(old, extras)
    

    Среди таких сомнительных и сомнительных ответов этот яркий пример является единственным и единственным хорошим способом объединения диктов в Python, одобренном диктатором на всю жизнь Гвидо ван Россум сам! Кто-то предложил половину этого, но не включил его в работу.

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

    дает:

    {'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
    
    ответ дан Sam Watkins, с репутацией 4336, 6.08.2012
  • 0 рейтинг

    Опираясь на идеи здесь и в других местах, я понял функцию:

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

    Использование (протестировано в Python 3):

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

    Вместо этого вы можете использовать лямбду.

    ответ дан Bijou Trouvaille, с репутацией 2990, 19.07.2013
  • 0 рейтинг

    Вопрос помечен как python-3x, но, принимая во внимание, что это относительно недавнее добавление, и что принятый ответ, получивший наибольшее количество голосов, широко посвящен Python 2. Решение, я осмелюсь добавить один вкладыш, который использует раздражающую особенность Python 2. x список понимания, то есть имя утечки . , ,

    $ 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}
    >>> ...
    

    Я рад сообщить, что вышесказанное больше не работает ни на одной версии Python 3.

    ответ дан gboffi, с репутацией 8031, 30.05.2017
  • 0 рейтинг

    Другой, более краткий, вариант:

    z = dict(x, **y)
    

    Примечание : это стало популярным ответом, но важно отметить, что если y имеет не строковые ключи, то, что это работает вообще, является злоупотреблением деталями реализации CPython, и это не работает в Python 3 или в PyPy, IronPython или Jython. Также Гвидо не фанат . Поэтому я не могу рекомендовать эту технику для совместимого с прямым переносом кода или переносимого кода с перекрестной реализацией, что на самом деле означает, что его следует полностью избегать.

    ответ дан Carl Meyer, с репутацией 57127, 2.09.2008
  • 0 рейтинг

    Если вы не возражаете, мутируя x,

    x.update(y) or x
    

    Простой, читабельный, производительный. Вы знаете, update() всегда возвращает None, что является ложным значением. Так что он всегда будет оценивать до x.

    Методы мутации в стандартной библиотеке, такие как update, по соглашению возвращают None, поэтому этот прием будет работать и над ними.

    Если вы используете библиотеку, которая не следует этому соглашению, вы можете использовать отображение и индекс кортежа, чтобы сделать его одним выражением вместо or, но это не так удобно для чтения.

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

    Если у вас еще нет x в переменной, вы можете использовать lambda для создания локального без использования оператора присваивания. Это равносильно использованию lambda в качестве выражения let 3230269583 let , что является распространенным методом в функциональных языках, но довольно непифонным.

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

    Если вам нужна копия, лучше всего PEP 448 {**x, **y}. Но если это не доступно, , пусть работает и здесь.

    (lambda z: z.update(y) or z)(x.copy())
    
    ответ дан gilch, с репутацией 1927, 22.09.2017
  • 0 рейтинг

    Python 3. 5 (PEP 448) допускает более приятную синтаксическую опцию:

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

    или даже

    final = {'a': 1, 'b': 1, **x, **y}
    
    ответ дан Bilal Syed Hussain, с репутацией 2636, 26.02.2015
  • 0 рейтинг

    Используя интеллектуальное понимание, вы можете

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

    дает

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

    Обратите внимание на синтаксис для if else в понимании

    { (some_key if condition else default_key):(something_if_true if condition 
              else something_if_false) for key, value in dict_.items() }
    
    ответ дан octoback, с репутацией 13234, 27.05.2013
  • 0 рейтинг

    Несмотря на то, что ответы были хороши для этого 3296269583 мелкого словаря , ни один из методов, определенных здесь, на самом деле не выполняет глубокое слияние словаря.

    Примеры следуют:

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

    Можно ожидать, что-то вроде этого:

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

    Вместо этого мы получаем это:

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

    Элемент 'one' должен иметь элементы 'глубины_2' и 'дополнительные значения' в качестве элементов внутри своего словаря, если он действительно был слиянием.

    Использование цепочки также не работает:

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

    Результаты в:

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

    Глубокое слияние, которое дал rcwesick, также создает тот же результат.

    Да, это будет работать для объединения образцов словарей, но ни один из них не является универсальным механизмом для объединения. Я обновлю это позже, когда напишу метод, который выполняет истинное слияние.

    ответ дан Thanh Lim, с репутацией 115, 3.08.2012
  • 0 рейтинг

    Рекурсивное / глубокое обновление dict

    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

    Демонстрация:

    pluto_original = {
        'name': 'Pluto',
        'details': {
            'tail': True,
            'color': 'orange'
        }
    }
    
    pluto_update = {
        'name': 'Pluutoo',
        'details': {
            'color': 'blue'
        }
    }
    
    print deepupdate(pluto_original, pluto_update)

    Выходы:

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

    Спасибо rednaw за правки.

    ответ дан Stan, с репутацией 2682, 29.11.2011
  • 0 рейтинг
    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)
    

    Звучит так, как будто вы очень плохо знакомы с Python, поэтому я хотел бы предложить решение, которое, на мой взгляд, наиболее читаемо тем, кто знает только о циклах for и перебирает ключи словаря. Псевдокод выглядит следующим образом:

    for each of the dictionaries in the list: 
        add each of the key-value pairs in that dictionary to our final dictionary.
    
    ответ дан Haziq Nordin, с репутацией 75, 4.12.2017
  • 0 рейтинг

    В Python 3. 5 вы можете использовать распаковать **, чтобы создать новый словарь. Этот метод не был показан в прошлых ответах. Кроме того, лучше использовать {} вместо dict(). Потому что {} является литералом Python, а dict() включает вызов функции.

    dict1 = {'a':1}
    dict2 = {'b':2}
    new_dict = {**dict1, **dict2}
    >>>new_dict
    {'a':1, 'a':2}
    
    ответ дан levi, с репутацией 13650, 28.09.2016
  • 0 рейтинг

    Я хотел что-то похожее, но с возможностью указать, как значения на дубликатах ключей были объединены, так что я взломал это (но не сильно протестировал это). Очевидно, что это не одно выражение, но это единственный вызов функции.

    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
    
    ответ дан rcreswick, с репутацией 9353, 4.09.2008
  • 0 рейтинг
    from collections import Counter
    dict1 = {'a':1, 'b': 2}
    dict2 = {'b':10, 'c': 11}
    result = dict(Counter(dict1) + Counter(dict2))
    

    Это должно решить вашу проблему.

    ответ дан reetesh11, с репутацией 157, 30.11.2015
  • 0 рейтинг

    (для Python2. Только 7 *; Существуют более простые решения для Python3 *. )

    Если вы не против импортировать стандартный библиотечный модуль, вы можете сделать

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

    (Бит or a в lambda необходим, потому что dict.update всегда возвращает None в случае успеха. )

    ответ дан kjo, с репутацией 11156, 28.03.2016
  • 0 рейтинг

    Вот код, кажется, работает нормально:

    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
    
    ответ дан user2571462, с репутацией 17, 11.07.2013
  • 0 рейтинг

    Будь питоном. Используйте понимание :

    z={i:d[i] for d in [x,y] for i in d}
    
    >>> print z
    {'a': 1, 'c': 11, 'b': 10}
    
    ответ дан Robino, с репутацией 1942, 20.01.2016
  • 0 рейтинг

    Если вы думаете, что лямбды - это зло, тогда не читайте дальше. По запросу вы можете написать быстрое и эффективное для памяти решение с одним выражением:

    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}
    

    Как предложено выше, лучше всего использовать две строки или написать функцию.

    ответ дан EMS, с репутацией 510, 23.11.2011
  • 0 рейтинг

    ** создает промежуточный dict, что означает, что общее количество копий на самом деле выше, делая форму dict(one, **two), но все, что происходит в C так что обычно это происходит быстрее, чем переход к itertools, за исключением случаев, когда существует огромное количество копий (или, возможно, если копии очень дорогие). Как всегда, если вы действительно заботитесь о скорости, вы должны рассчитать время использования.

    Сроки на Python 2. 7. 3 с пустым диктом:

    $ 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 (крошечных) предметов:

    $ 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 предметов:

    $ 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 предметов:

    $ 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
    
    ответ дан quodlibetor, с репутацией 4800, 6.09.2013