简体   繁体   中英

How to delete dictionary items if their keys are not in a list, using Python

How to delete a larger number of dictionary items that are not in a list? For example, there is a dictionary dct and a list `lst:

dct = {'a' : 2, 'b' : 4, 'c' : 6, 'd' : 7}
lst = ['a', 'c']

What would be the most efficient way to filter out the dictionary so that it results in:

dct.items()

Output:

dict_items([('a', 2), ('c', 6)])

Thanks!

Is it a requirement that you mutate the existing dictionary, or is producing a new, smaller dictionary okay?

If you can produce a new dictionary, the phrasing of your question might direct you to Python's filter function, which would you implement along the lines of (assuming key_list is the list of key values you want to keep):

 new_dict = filter(lambda pair: pair[0] in key_list, old_dict)

You could also do this with a dictionary comprehension, along the lines of:

 new_dict = { key : value for (key, value) in old_dict if key in key_list }

If you absolutely, positively must mutate the original dictionary there are ways to do this in a single line in Python but they would not be entirely clear to a Python programmer, so I'd probably do it in a loop:

for key in old_dict:
     if key not in key_list:
          del old_dict[key]

This works in Python 2 but not Python 3 where the deletion inside the for loop will break the iteration. For Python 3 (I think) you need to do something like:

del_keys = [ key for key in old_dict if key not in key_list ]
for key in del_keys:
     del old_dict[key]

The simplest way to get a new dictionary is to iterate through the list, not the dictionary:

new_dict = {k: dct[k] for k in lst if k in dct}

Notice that this is O(N) over the keys rather than O(M * N) over both the keys and the dictionary. The lookup k in dct is O(1) , while the lookup k in lst is O(N) . Assuming that the list is shorter than the dictionary, it's better than iterating over the dictionary if you did it efficiently, since that would be O(M) > O(N) .

If your list is guaranteed to contain a subset of the dictionary's elements, you can skip the check if k in dct entirely.

If you must process the original dictionary in-place, you can do one of two things. The easier solution is to use the new dictionary:

new_dict = {k: dct[k] for k in lst if k in dct}
dct.clear()
dct.upate(new_dict)

If that's cheating, you can iterate over the dictionary. For fast lookup, turn the list into a set first:

s = set(lst)
for k in list(dct.keys()):
    if k not in lst:
        del dct[k]

Here is one method:

dct = {'a' : 2, 'b' : 4, 'c' : 6, 'd' : 7}
lst = ['b', 'd']
ndct = {}
for l in list(dct):
    if l in lst:
        pass
    else:
        ndct[l] = dct[l]

ndct equal to:

{'a': 2, 'c': 6}

A simple code:

dct = {'a' : 2, 'b' : 4, 'c' : 6, 'd' : 7}
lst = ['b', 'd']

for key in list(dct):
    if key in lst:
        dct.pop(key)

Result:

{'a': 2, 'c': 6}

As Mark Byers said, you must use the list function to get a copy of the keys, otherwise, the error of “RuntimeError: dictionary changed size during iteration” will happen. Works on versions 2 and 3 of python.

You can find the intersection between dictionary keys and list values:

dct = {'a' : 2, 'b' : 4, 'c' : 6, 'd' : 7}
lst = ['a', 'c']

{k: dct[k] for k in dct.keys() & lst}

Output:

{'c': 6, 'a': 2}

You can use the list of words that are to be removed from the dictionary and print the dictionary if the key is not present in the list. The code is as below:

dct={key:val for key, val in dct.items() if key not in lst}

just print the dct.items() and you will get the result you wanted

You will get the desired output of dictionary being reset with only the values that are not present in the list(lst).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM