0

I have written the below code for the task of removing every Null or empty content. The script works, however I think it is not "pytonish" at all. How would be the python way to do it ?

def remove_empty_values(ret):
    #ret is assumed eitehr dict or list
    #recursively remove all key or list items which values is Null or empty string
    if type(ret) == list:
            empty_indexes=[]
            i = 0
            for index in ret:
                    if (ret[i] == None) or ((type(ret[i]) == str and  ret[i] == '') or ((type(ret[i]) == unicode and  ret[i] == '') or (( type(ret[i])==dict or type(ret[i])==list )  and len(ret[i]) ==0))):
                            empty_indexes.append(i)
                    else:
                             if (type(ret[i])==dict or type(ret[i])==list):
                                    remove_empty_values(ret[i])
                    i = i + 1
            for index in empty_indexes:
                    del ret[index]

    elif type(ret) == dict:

            empty_keys=[]
            for key in ret:
                    if (ret[key] == None) or ((type(ret[key]) == str and ret[key] == '') or ((type(ret[key]) == unicode and ret[key] == '') or (( type(ret[key])==dict or type(ret[key])==list )  and len(ret[key]) ==0))):
                            empty_keys.append(key)
                    else:
                             if (type(ret[key])==dict or  type(ret[key])==list):
                                    remove_empty_values(ret[key])
            for key in empty_keys:
                    del ret[key]
3
  • What about it do you think is not "pythonish"? Commented Jun 27, 2020 at 21:32
  • check filter() Commented Jun 27, 2020 at 21:37
  • @ScottHunter well it is too long for the task it does, the for cycle, the I = I +1, I was developing in C++ and I feel this is a C-Style code :) Commented Jun 29, 2020 at 13:59

1 Answer 1

2

If you use Python 3.8+, you can use assignment expression :=:

For example:

d = {'a': [{'b': 'x', 'c': ''}], 'c': ['', '1', None], 'd': ['']}


def remove(i):
    if isinstance(i, dict):
        return {k: vv for k, v in i.items() if (vv:=remove(v))}
    elif isinstance(i, list):
        return [vv for v in i if (vv:=remove(v))]
    return i

print(remove(d))

Prints:

{'a': [{'b': 'x'}], 'c': ['1']}

EDIT: To keep zeros and False:

d = {'a': [{'b': 'x', 'c': ''}], 'c': ['', '1', None], 'd': ['', 0, False]}


def remove(i):
    if isinstance(i, dict):
        return {k: vv for k, v in i.items() if (vv:=remove(v)) or v is False or v == 0}
    elif isinstance(i, list):
        return [vv for v in i if (vv:=remove(v)) or v is False or v == 0]
    return i

print(remove(d))

Prints:

{'a': [{'b': 'x'}], 'c': ['1'], 'd': [0, False]}
Sign up to request clarification or add additional context in comments.

2 Comments

But this would kill the boolean false values is, wouldn't it ?
I need to keep the 0s and the explicit boolean false values as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.