Merge Dictionaries Preserving Old Keys and New Values
<p>I'm writing a Python script that parses RSS feeds. I want to maintain a dictionary of entries from the feed that gets updated periodically. Entries that no longer exist in the feed should be removed, new entries should get a default value, and the values for previously seen entries should remain unchanged.</p>

<p>This is best explained by example, I think:</p>

<pre><code>&gt;&gt;&gt; old = {
...     'a': 1,
...     'b': 2,
...     'c': 3
... }
&gt;&gt;&gt; new = {
...     'c': 'x',
...     'd': 'y',
...     'e': 'z'
... }
&gt;&gt;&gt; out = some_function(old, new)
&gt;&gt;&gt; out
{'c': 3, 'd': 'y', 'e': 'z'}
</code></pre>

<p>Here's my current attempt at this:</p>

<pre><code>def merge_preserving_old_values_and_new_keys(old, new):
       out = {}
       for k, v in new.items():
           out[k] = v
       for k, v in old.items():
           if k in out:
               out[k] = v
       return out
</code></pre>

<p>This works, but it seems to me there might be a better or more clever way.</p>

<p>EDIT: If you feel like testing your function:</p>

<pre><code>def my_merge(old, new):
    pass

old = {'a': 1, 'b': 2, 'c': 3}
new = {'c': 'x', 'd': 'y', 'e': 'z'}

out = my_merge(old, new)
assert out == {'c': 3, 'd': 'y', 'e': 'z'}
</code></pre>

<p>EDIT 2:
Defining Martijn Pieters' answer as <code>set_merge</code>, bravosierra99's as <code>loop_merge</code>, and my first attempt as <code>orig_merge</code>, I get the following timing results:</p>

<pre><code>&gt;&gt;&gt; setup="""
... old = {'a': 1, 'b': 2, 'c': 3}
... new = {'c': 'x', 'd': 'y', 'e': 'z'}
... from __main__ import set_merge, loop_merge, orig_merge
... """
&gt;&gt;&gt; timeit.timeit('set_merge(old, new)', setup=setup)
3.4415210600000137
&gt;&gt;&gt; timeit.timeit('loop_merge(old, new)', setup=setup)
1.161155690000669
&gt;&gt;&gt; timeit.timeit('orig_merge(old, new)', setup=setup)
1.1776735319999716
</code></pre>

<p>I find this surprising, since I didn't expect the dictionary view approach to be that much slower.</p>

<p>Dictionaries have <a href="https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects" rel="nofollow"><em>dictionary view objects</em></a> that act as sets. Use these to get the intersection between old and new:</p>

<pre><code>def merge_preserving_old_values_and_new_keys(old, new):
    result = new.copy()
    result.update((k, old[k]) for k in old.viewkeys() &amp; new.viewkeys())
    return result
</code></pre>

<p>The above uses the Python 2 syntax; use <code>old.keys() &amp; new.keys()</code> if you are using Python 3, for the same results:</p>

<pre><code>def merge_preserving_old_values_and_new_keys(old, new):
    # Python 3 version
    result = new.copy()
    result.update((k, old[k]) for k in old.keys() &amp; new.keys())
    return result
</code></pre>

<p>The above takes all key-value pairs from <code>new</code> as a starting point, then adds the values for <code>old</code> for any key that appears in both.</p>

<p>Demo:</p>

<pre><code>&gt;&gt;&gt; merge_preserving_old_values_and_new_keys(old, new)
{'c': 3, 'e': 'z', 'd': 'y'}
</code></pre>

<p>Note that the function, like your version, produces a new dictionary (albeit that the key and value objects are shared; it is a shallow copy).</p>

<p>You could also just update the new dictionary in-place if you don't need that new dictionary for anything else:</p>

<pre><code>def merge_preserving_old_values_and_new_keys(old, new):
    new.update((k, old[k]) for k in old.viewkeys() &amp; new.viewkeys())
    return new
</code></pre>

<p>You could also use a one-liner dict comprehension to build a new dictionary:</p>

<pre><code>def merge_preserving_old_values_and_new_keys(old, new):
    return {k: old[k] if k in old else v for k, v in new.items()}
</code></pre>

python dictionary