0

i have a nested python dictionary where i am trying to remove all keys except those mentioned. I found a solution here where we can remove keys specified, what i am trying to do is reverse of it, i want to remove all keys except those mentioned. So i made a slight change in the function, but i am getting an empty dict.

from collections import MutableMapping


def remove_fields(d, list_of_keys_to_remove):
    if not isinstance(d, (dict, list)):
        return d
    if isinstance(d, list):
        return [v for v in (remove_fields(v, list_of_keys_to_remove) for v in d) if v]
    return {k: v for k, v in ((k, remove_fields(v, list_of_keys_to_remove)) for k, v in d.items()) if
            k in list_of_keys_to_remove}

Adding sample input EDIT: let suppose i want to keep RENEWAL_TYPE

{
  'G_1': [
    {
      'ACCOUNTING_RULE_ID': '1',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    },
    {
      'ACCOUNTING_RULE_ID': '2',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    },
    {
      'ACCOUNTING_RULE_ID': '3',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'DO_NOT_RENEW'
    },
    {
     'ACCOUNTING_RULE_ID': '4',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    }
  ]
}
noobie-php
  • 6,817
  • 15
  • 54
  • 101

3 Answers3

1

You're looking for the intersection between the set of keys in the dict and the set of values in the list. i.e. all keys that exist in both sets.

Try this:

from collections import MutableMapping


d = { 'A': 1, 'B': 2, 'C': 3, 'D': 4 }
list_of_keys_to_keep = ['B', 'C', 'F']

def remove_fields(d, list_of_keys_to_keep):
    return {key: value for key, value in d.items() if key in list_of_keys_to_keep}

print(remove_fields(d, list_of_keys_to_keep)) # -> {'B': 2, 'C': 3}

Edit: Updated name of list_of_keys_to_remove to list_of_keys_to_keep since this seems to be what it actually represents.

Edit2: Updated after Askers update. The following works for the sample provided:

from collections import MutableMapping

d = {
  'G_1': [
    {
      'ACCOUNTING_RULE_ID': '1',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    },
    {
      'ACCOUNTING_RULE_ID': '2',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    },
    {
      'ACCOUNTING_RULE_ID': '3',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'DO_NOT_RENEW'
    },
    {
     'ACCOUNTING_RULE_ID': '4',
      'PAYMENT_TERM_ID': '4',
      'RENEWAL_TYPE': 'RENEW'
    }
  ]
}
list_of_keys_to_keep = ['RENEWAL_TYPE']

def filter_dict(di, keys):
    if not isinstance(di, (dict, list)):
        return di
    if isinstance(di, list):
        return [filter_dict(value, keys) for value in di]
    return {key: filter_dict(value, keys) for key, value in di.items() if key in keys or isinstance(value, (dict, list))}

print(filter_dict(d, list_of_keys_to_keep))

Output:

{'G_1': [{'RENEWAL_TYPE': 'RENEW'}, {'RENEWAL_TYPE': 'RENEW'}, {'RENEWAL_TYPE': 'DO_NOT_RENEW'}, {'RENEWAL_TYPE': 'RENEW'}]}
Jim Nilsson
  • 838
  • 4
  • 12
0

try this one:

dict = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
keys_to_preserve = ["e", "b", "c"]

dict_final={k: v for k,v in dict.items() if k in keys_to_preserve}
Grzegorz Skibinski
  • 12,624
  • 2
  • 11
  • 34
0
def remove_fields(d, keys_to_preserve):
    if isinstance(d, list):
        return [remove_fields(v, keys_to_preserve) for v in d]
    elif isinstance(d, dict):
        return dict([(k, remove_fields(v, keys_to_preserve)) for k, v in d.items() if k in keys_to_preserve])
    else:
        return d
Misza
  • 635
  • 4
  • 15