-1

There are two dictionaries as follow which I want to merge them, my point is to select those keys that I am interested in, for example I am interested in all the keys except county. Solution I 've used is using del function after creating your new dictionary, however I am sure there are more ways that are more efficient to my solution. How can I solve this problem without del function using UNPACKING ARGUMENT.

    >>> d1 =  {'avgUserperDay': '12', 'avgPurchaseperDay': '1', 'country': 'Japan'}
    >>> d2 = {'tUser': 1, 'tPurchase': 0, 'country': 'Japan'}
    >>> d ={**d1,**d2}
    >>>{'tUser': 1, 'tPurchase': 0, 'avgPurchaseperDay': '1', 'avgUserperDay': '12', 'country': 'Japan'}
    >>> del d['country']
    >>> d
    {'tUser': 1, 'tPurchase': 0, 'avgPurchaseperDay': '1', 'avgUserperDay': '12'}

AFTER DISCUSSION,

This command works with 3.5.1,

>>> {**{k:v for k, v in chain(d1.items(), d2.items()) if k != 'country'}}
{'tUser': 1, 'tPurchase': 0, 'avgPurchaseperDay': '1', 'avgUserperDay': '12'}
pm1359
  • 622
  • 1
  • 10
  • 31

3 Answers3

1

why would you want to do it using argument unpacking? just do:

from itertools import chain
d = {key:value for key, value in chain(d1.iteritems(), d2.iteritems())
     if key not in keys_to_ignore}

where keys_to_ignore is list/set/tuple of keys you want to ignore

Alex
  • 1,141
  • 8
  • 13
1

How can I solve this problem without del function using UNPACKING ARGUMENT?

Yes, you can. But you should not. Ideal way should be:

d1.update(d2)   # values will be updated in d1 dict
del d1['country']

There no direct way to meet your conditions:

  • create new dict using argument unpacking
  • not using del to remove country.

But there are work around if this is what you want. For example using itertools.chain() with dict comprehension as:

{**{k:v for k, v in chain(d1.items(), d2.items()) if k != 'country'}}

Note: For those curios about how {**dict1, **dict2} even works. It is new syntax supported since from python 3.5+, proposed in PEP 448. Check: What's New in Python 3.5 document.

Since, {**dict1, **dict2} is only supported in Python 3.5+, for earlier version of Python, you can do (as mentioned by S. De Melo):

d = dict(d1, **d2)
d.pop("country")

OR without using ** as:

{k, v for k, v in chain(d1.iteritems(), d2.iteritems()) if k != 'country'}
Community
  • 1
  • 1
Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
  • Does this work in Python 2? The `{**{` is a syntax error in Python 3 – Patrick Haugh Oct 05 '16 at 13:31
  • It is supported only in Python 3.5+. But since user has specified in the sample code that it is working. I edited question with the 3.5 tag – Moinuddin Quadri Oct 05 '16 at 13:32
  • @MoinuddinQuadri in python3 i've got SyntaxError: invalid syntax. – pm1359 Oct 05 '16 at 13:35
  • @PatrickHaugh : Check [What's new in Python 3.5](https://docs.python.org/dev/whatsnew/3.5.html#pep-448-additional-unpacking-generalizations) – Moinuddin Quadri Oct 05 '16 at 13:47
  • @MoinuddinQuadri I am using version 3.5.1, also in my question you can see i have used unpacking argument and it works. – pm1359 Oct 05 '16 at 14:12
  • thx, I have added the correct one in description, u should use as above with 3.5.1, u can't use iteritems here.. – pm1359 Oct 05 '16 at 14:16
  • error with this command is `ValueError: too many values to unpack (expected 2)`, by the way thx for your explanations – pm1359 Oct 05 '16 at 14:25
1

If you don't want to use del, you can replace it by .pop(key). For example, using unpacking argument too:

d = dict(d1, **d2)
d.pop("country")

Notice that .pop returns the value too (here "Japan").

S. de Melo
  • 786
  • 4
  • 11