3

Consider i have dict. Ex.

 dict1 = {"1434": {"2012-10-29": {"275174": {"declaration_details":
 {"UTCC": `"38483 "`, "CNRE": "8334", "CASH": "55096.0"},
 "sales_details": {"UTCC": "38483.0", "CNRE": "8334.0", "CASH":
 "55098.0"}}, "275126": {"declaration_details": {"CNIS": "63371"},
 "sales_details": {"CNIS": "63371.0"}}, "275176":
 {"declaration_details": {"UTCC": "129909", "CASH": `"93200.0 "`,
 "CNRE": "28999", "PBGV": "1700"}, "sales_details": {"UTCC":
 "131619.0", "PBGV": "1700.0", "CASH": "92880.0", "CNRE": "28999.0"}},
 "275169": {"declaration_details": {"AMCC": "118616", "CNRE": "19462",
 "CASH": "120678.0"}, "sales_details": {"UTCC": "118616.0", "CNRE":
 "19462.0", "CASH": "120677.0"}}, "266741": {"declaration_details":
 {"UTCC": "42678", "CNRE": "4119", "CASH": `"24944.0 "`},
 "sales_details": {"UTCC": "42678.0", "CNRE": "4119.0", "CASH":
 "24944.0"}}}}}

i wanted to removed all white spaces in that dict1.

Which is the better way to do that?

Vinay
  • 6,891
  • 4
  • 32
  • 50
Niks Jain
  • 1,617
  • 5
  • 27
  • 53

5 Answers5

7
def removew(d):
  for k, v in d.iteritems():
    if isinstance(v, dict):
      removew(v)
    else:
      d[k]=v.strip()


removew(dict1)
print dict1

output:

{'1434': {'2012-10-29': {'275174': {'declaration_details': {'UTCC': '38483', 'CNRE': '8334', 'CASH': '55096.0'}, 'sales_details': {'UTCC': '38483.0', 'CNRE': '8334.0', 'CASH': '55098.0'}}, '275126': {'declaration_details': {'CNIS': '63371'}, 'sales_details': {'CNIS': '63371.0'}}, '275176': {'declaration_details': {'UTCC': '129909', 'CNRE': '28999', 'CASH': '93200.0', 'PBGV': '1700'}, 'sales_details': {'UTCC': '131619.0', 'CNRE': '28999.0', 'CASH': '92880.0', 'PBGV': '1700.0'}}, '275169': {'declaration_details': {'CNRE': '19462', 'AMCC': '118616', 'CASH': '120678.0'}, 'sales_details': {'UTCC': '118616.0', 'CNRE': '19462.0', 'CASH': '120677.0'}}, '266741': {'declaration_details': {'UTCC': '42678', 'CNRE': '4119', 'CASH': '24944.0'}, 'sales_details': {'UTCC': '42678.0', 'CNRE': '4119.0', 'CASH': '24944.0'}}}}}

EDIT: As noted by Blckknght,the first solution, will break, if you strip() keys that contain whitespace (old key,value pairs remain in the dict). If you need to strip both use dict comprehension, returning a new dict (available since python 2.7).

def removew(d):
    return   {k.strip():removew(v)
             if isinstance(v, dict)
             else v.strip()
             for k, v in d.iteritems()}
removew(dict1)
root
  • 76,608
  • 25
  • 108
  • 120
  • 2
    This is mostly right (and almost the same as my answer), but it won't do the right thing if there is whitespace in a key. The old key:value pair will remain. Also, it may break your dictionary if you add and remove keys from it while iterating (you may skip some, or see some multiple times, or demons may fly out of your nose). – Blckknght Oct 31 '12 at 07:00
7

I think a recursive function may be your best approach. This way you don't need to worry about what depth of nested dictionaries your whitespace is located at.

def strip_dict(d):
    return { key : strip_dict(value)
             if isinstance(value, dict)
             else value.strip()
             for key, value in d.items() }

If you want to remove whitespace from keys in addition to values, just replace key with key.strip() in the first row of the dictionary comprehension.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • If your `value` is of type `int`, in that case `value.strip()` will fail. A duct tape solution would be to replace `value` with `str(value)` in the third row of the dictionary comprehension. – Ronnie Mar 02 '20 at 18:17
  • @Ronnie: It doesn't make any sense to be talking about removing white space from integer values, so I assumed that the dictionary looks like the one in the question, with strings (even for numerical values). Python doesn't convert between `123` and `"123"`, so you shouldn't ever be mixing them up. If you have one in your data structure when you expect the other, you surely have a bug. – Blckknght Mar 02 '20 at 19:13
  • Fair point. I do happen to have a JSON object though, which is parsed as a `dict` and has an integer value for a key, within another dictionary sub-element. – Ronnie Mar 02 '20 at 21:21
3

Here's a function that will strip whitespace not just from values, but keys too.

It recurses when it finds a dictionary, just like the other answers:

def strip_dict(d):
    """
    Recursively remove whitespace from keys and values in dictionary 'd'
    """

    for key, value in d.iteritems():
        if ' ' in key:
            d[key.strip()] = value
            del d[key]
        if isinstance(value, dict):
            strip_dict(value)
        elif isinstance(value, list):
            d[key.strip()] = [x.strip() for x in value]
        elif isinstance(value, str):
            d[key.strip()] = value.strip()
nonbeing
  • 6,907
  • 6
  • 36
  • 46
1

I needed a function to clean all whitespace in a nested dictionary containing other dicts or lists or whatever. This should help, i used the above answers.

def strip_dict(d):
    def strip_list(l):
        return [strip_dict(x)
        if isinstance(x, dict)
        else strip_list(x)
        if isinstance(x, list)
        else clean(value) 
        for x in l]

    def clean(string):
        return ''.join(string.split())

    return { key.strip() : strip_dict(value)
             if isinstance(value, dict)
             else strip_list(value)
             if isinstance(value, list)
             else value
             if isinstance(value, bool)
             else clean(value)
             for key, value in d.items() }
Mike
  • 466
  • 9
  • 24
  • your code is fine but will break on int/float values... here a possible fix: if isinstance(value(bool, float, int)) else clean(value) – nicolasassi Jul 29 '20 at 13:53
0

As The above answer is in the right path but has some errors and does not consider some possibilities I'm posting my version of the answer which strips both keys and values recursively.

def strip_dict_keys_values(d):
    def strip_list(l):
        return [strip_dict_keys_values(x)
                if isinstance(x, dict) else strip_list(x)
                if isinstance(x, list) else clean(x) for x in l]

    def clean(value):
        if isinstance(value, str):
            return value.strip()
        return value

    return {key.strip(): strip_dict_keys_values(value)
            if isinstance(value, dict) else strip_list(value)
            if isinstance(value, list) else clean(value)
            if value is None else clean(value)
            for key, value in d.items()}
nicolasassi
  • 490
  • 4
  • 14