Efficient way to remove keys with empty strings from a dict

前端 未结 17 1134

I have a dict and would like to remove all the keys for which there are empty value strings.

metadata = {u\'Composite:PreviewImage\': u\'(Binary data 101973          


        
相关标签:
17条回答
  • 2020-11-27 13:26

    "As I also currently write a desktop application for my work with Python, I found in data-entry application when there is lots of entry and which some are not mandatory thus user can left it blank, for validation purpose, it is easy to grab all entries and then discard empty key or value of a dictionary. So my code above a show how we can easy take them out, using dictionary comprehension and keep dictionary value element which is not blank. I use Python 3.8.3

    data = {'':'', '20':'', '50':'', '100':'1.1', '200':'1.2'}
    
    dic = {key:value for key,value in data.items() if value != ''}
    
    print(dic)
    
    {'100': '1.1', '200': '1.2'}
    
    0 讨论(0)
  • 2020-11-27 13:30

    I read all replies in this thread and some referred also to this thread: Remove empty dicts in nested dictionary with recursive function

    I originally used solution here and it worked great:

    Attempt 1: Too Hot (not performant or future-proof):

    def scrub_dict(d):
        if type(d) is dict:
            return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v))
        else:
            return d
    

    But some performance and compatibility concerns were raised in Python 2.7 world:

    1. use isinstance instead of type
    2. unroll the list comp into for loop for efficiency
    3. use python3 safe items instead of iteritems

    Attempt 2: Too Cold (Lacks Memoization):

    def scrub_dict(d):
        new_dict = {}
        for k, v in d.items():
            if isinstance(v,dict):
                v = scrub_dict(v)
            if not v in (u'', None, {}):
                new_dict[k] = v
        return new_dict
    

    DOH! This is not recursive and not at all memoizant.

    Attempt 3: Just Right (so far):

    def scrub_dict(d):
        new_dict = {}
        for k, v in d.items():
            if isinstance(v,dict):
                v = scrub_dict(v)
            if not v in (u'', None, {}):
                new_dict[k] = v
        return new_dict
    
    0 讨论(0)
  • 2020-11-27 13:30

    An alternative way you can do this, is using dictionary comprehension. This should be compatible with 2.7+

    result = {
        key: value for key, value in
        {"foo": "bar", "lorem": None}.items()
        if value
    }
    
    0 讨论(0)
  • 2020-11-27 13:35

    Based on Ryan's solution, if you also have lists and nested dictionaries:

    For Python 2:

    def remove_empty_from_dict(d):
        if type(d) is dict:
            return dict((k, remove_empty_from_dict(v)) for k, v in d.iteritems() if v and remove_empty_from_dict(v))
        elif type(d) is list:
            return [remove_empty_from_dict(v) for v in d if v and remove_empty_from_dict(v)]
        else:
            return d
    

    For Python 3:

    def remove_empty_from_dict(d):
        if type(d) is dict:
            return dict((k, remove_empty_from_dict(v)) for k, v in d.items() if v and remove_empty_from_dict(v))
        elif type(d) is list:
            return [remove_empty_from_dict(v) for v in d if v and remove_empty_from_dict(v)]
        else:
            return d
    
    0 讨论(0)
  • 2020-11-27 13:36

    If you have a nested dictionary, and you want this to work even for empty sub-elements, you can use a recursive variant of BrenBarn's suggestion:

    def scrub_dict(d):
        if type(d) is dict:
            return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v))
        else:
            return d
    
    0 讨论(0)
  • 2020-11-27 13:38

    Here is an option if you are using pandas:

    import pandas as pd
    
    d = dict.fromkeys(['a', 'b', 'c', 'd'])
    d['b'] = 'not null'
    d['c'] = ''  # empty string
    
    print(d)
    
    # convert `dict` to `Series` and replace any blank strings with `None`;
    # use the `.dropna()` method and
    # then convert back to a `dict`
    d_ = pd.Series(d).replace('', None).dropna().to_dict()
    
    print(d_)
    
    0 讨论(0)
提交回复
热议问题