Return copy of dictionary excluding specified keys

PythonDictionaryKeyDictionary Comprehension

Python Problem Overview


I want to make a function that returns a copy of a dictionary excluding keys specified in a list.

Considering this dictionary:

my_dict = {
    "keyA": 1,
    "keyB": 2,
    "keyC": 3
}

A call to without_keys(my_dict, ['keyB', 'keyC']) should return:

{
    "keyA": 1
}

I would like to do this in a one-line with a neat dictionary comprehension but I'm having trouble. My attempt is this:

def without_keys(d, keys):
	return {k: d[f] if k not in keys for f in d}

which is invalid syntax. How can I do this?

Python Solutions


Solution 1 - Python

You were close, try the snippet below:

>>> my_dict = {
...     "keyA": 1,
...     "keyB": 2,
...     "keyC": 3
... }
>>> invalid = {"keyA", "keyB"}
>>> def without_keys(d, keys):
...     return {x: d[x] for x in d if x not in keys}
>>> without_keys(my_dict, invalid)
{'keyC': 3}

Basically, the if k not in keys will go at the end of the dict comprehension in the above case.

Solution 2 - Python

In your dictionary comprehension you should be iterating over your dictionary (not k , not sure what that is either). Example -

return {k:v for k,v in d.items() if k not in keys}

Solution 3 - Python

This should work for you.

def without_keys(d, keys):
    return {k: v for k, v in d.items() if k not in keys}

Solution 4 - Python

Even shorter. Apparently python 3 lets you 'subtract' a list from a dict_keys.

def without_keys(d, keys):
    return {k: d[k] for k in d.keys() - keys}

Solution 5 - Python

For those who don't like list comprehensions, this is my version:

def without_keys(d, *keys):
     return dict(filter(lambda key_value: key_value[0] not in keys, d.items()))

Usage:

>>> d={1:3, 5:7, 9:11, 13:15}
>>> without_keys(d, 1, 5, 9)
{13: 15}
>>> without_keys(d, 13)
{1: 3, 5: 7, 9: 11}
>>> without_keys(d, *[5, 7])
{1: 3, 13: 15, 9: 11}

Solution 6 - Python

You could this generalized for nested dictionaries solution

def copy_dict(data, strip_values=False, remove_keys=[]):
    if type(data) is dict:
        out = {}
        for key, value in data.items():
            if key not in remove_keys:
                out[key] = copy_dict(value, strip_values=strip_values, remove_keys=remove_keys)
        return out
    else:
        return [] if strip_values else data

This recursive solution works for nested dictionaries and removes keys not required from the entire nested structure. It also gives you the ability to return the nest with only keys and no values.

Solution 7 - Python

Your oneliner

my_dict = {"keyA": 1, "keyB": 2, "keyC": 3}
(lambda keyB, keyC, **kw: kw)(**my_dict)

which returns {'keyA': 1}. Not very pythonic and dynamic, but hacky and short. It uses the dict unpacking (destructuring assignment) of function arguments.

See also https://stackoverflow.com/a/53851069/11769765.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJuicyView Question on Stackoverflow
Solution 1 - PythonAnshul GoyalView Answer on Stackoverflow
Solution 2 - PythonAnand S KumarView Answer on Stackoverflow
Solution 3 - PythonMorgan ThrappView Answer on Stackoverflow
Solution 4 - PythonMike FogelView Answer on Stackoverflow
Solution 5 - PythonHimel DasView Answer on Stackoverflow
Solution 6 - PythonRakshit KothariView Answer on Stackoverflow
Solution 7 - PythonFriedrichView Answer on Stackoverflow