Home > front end >  create a list of a dictionary that meets the condition of the dictionary values
create a list of a dictionary that meets the condition of the dictionary values

Time:10-10

hi I am new to python and I am trying to filter this dictionary with its values containing an empty list or a null value. below is the dictionary called response:

response = {'name': 'py', 
'title': 'Py', 
'description': 'Python library and collection of scripts that automate work on MediaWiki sites', 'url': 'https://www.me', 
'keywords': [], 
'author': [{'name': 'team'}], 
'repository': 'https://gecore', 
'subtitle': None, 
'id': None, 
'alternates': [], 
'username': None, 
'deprecated': False, 
'by': None, 
'experimental': False, 
'for': ['*'], 
'icon': 'https://commons.wikimedia.org/wiki/File:Pywikibot_MW_gear_icon.svg', 
'license': 'MIT', 
'sponsor': [], 
'available_languages': [], 
'technology_used': ['python'], 
'tool_type': 'framework', 
'api': None, 
'developer_url': [{'d_url': 'https://www.mement', 'language': 'en'}], 
'user_url': [{'language': 'en', 'm_url': 'https://www.Spec'}, {'t_url': 'https://doc.media', 'language': 'en'}], 
'feedback': [], 
'privacy': [], 
'translate_url': 'https://translate.bot', 
'bugtracker_url': 'https://phabbot/', 
'annotations': {
'wid': None, 
'depre': False, 
'by': None, 
'exp': False, 
'for': [], 
'icon': None, 
'available_languages': ['en'], 
'ttype': None, 
'rey': Null, 
'api': None, 
'dev_doc': [{'url': 'https://www.medial:t', 'language': 'en'}], 'user_url': [], 
'feedback': [], 
'privacy': [], 
'translat': None, 
'bugtracker': None}, 
'_schema': None, 
'_language': 'en', 
'origin': 'api', 
'created_by': {'id': 10, 'username': 'JJMC89'}, 
'created_date': '2021-10-12T20:26:29.012245Z', 
'modified_by': {
'id': 3, 
'username': 'BD'
}, 
'modified_date': Null}

my code:

print([response if response.values() == [] or Null or None])

i got an error while running this on jupyter notebook. my code is trying to filter the dictionary with the condition( where the values of the dictionary has an empty list or a null value) - to create a list of dictionary that meets this condition.

CodePudding user response:

print([v for v in response.values() if v != [] and v is not None])

CodePudding user response:

Null is not a Keyword in python.

So, you will have to convert it to None or "Null"

print([resp for resp in response.values() if resp == [] or resp == "Null" or resp == None])

CodePudding user response:

The error here is that you only compare the response to the empty list [] but not to None. Basically what you are doing is asking if the value is an empty list or if None, but only that. What you want to do is separate the condition, such as

print([r for r in response.values() if not r or r is None])

The not r catches both an empty list and the boolean False.

Alternatively you can use the filter function

list(filter(lambda x: not x, response.values()))

But that will give you only the values. If you want the keys, you might want to do:

print([k for k,v in response.items() if not v])

That will output

['keywords', 'subtitle', 'id', 'alternates', 'username', 'deprecated', 'by', 'experimental', 'sponsor', 'available_languages', 'api', 'feedback', 'privacy', '_schema', 'modified_date']

If you want to also support the nested dicts, a single line might not be enough, but recursion might do it.

def get_nones(resp, result):
...     for k, v in resp.items():
...             if not v:
...                     result.append(k)
...             elif isinstance(v, dict):
...                     get_nones(v, result)
...     return result
... 
>>> r = []
>>> get_nones(response, r)
['keywords', 'subtitle', 'id', 'alternates', 'username', 'deprecated', 'by', 'experimental', 'sponsor', 'available_languages', 'api', 'feedback', 'privacy', 'wid', 'depre', 'by', 'exp', 'for', 'icon', 'ttype', 'rey', 'api', 'user_url', 'feedback', 'privacy', 'translat', 'bugtracker', '_schema', 'modified_date']

by the way, this works because Python passes its lists by reference and not by value. The last line of the function return result is just to have it at the end, but there is no need to update the value during recursion as it is the same object that is being passed.

Hope it helps

CodePudding user response:

Null does not exists. You can use np.nan from numpy.

response = {'name': 'py', 
    'title': 'Py', 
    'description': 'Python library and collection of scripts that automate work on MediaWiki sites', 'url': 'https://www.me', 
    'keywords': [], 
    'author': [{'name': 'team'}], 
    'repository': 'https://gecore', 
    'subtitle': None, 
    'id': None, 
    'alternates': [], 
    'username': None, 
    'deprecated': False, 
    'by': None, 
    'experimental': False, 
    'for': ['*'], 
    'icon': 'https://commons.wikimedia.org/wiki/File:Pywikibot_MW_gear_icon.svg', 
    'license': 'MIT', 
    'sponsor': [], 
    'available_languages': [], 
    'technology_used': ['python'], 
    'tool_type': 'framework', 
    'api': None, 
    'developer_url': [{'d_url': 'https://www.mement', 'language': 'en'}], 
    'user_url': [{'language': 'en', 'm_url': 'https://www.Spec'}, {'t_url': 'https://doc.media', 'language': 'en'}], 
    'feedback': [], 
    'privacy': [], 
    'translate_url': 'https://translate.bot', 
    'bugtracker_url': 'https://phabbot/', 
    'annotations': {
    'wid': None, 
    'depre': False, 
    'by': None, 
    'exp': False, 
    'for': [], 
    'icon': None, 
    'available_languages': ['en'], 
    'ttype': None, 
    'rey': np.nan, 
    'api': None, 
    'dev_doc': [{'url': 'https://www.medial:t', 'language': 'en'}], 'user_url': [], 
    'feedback': [], 
    'privacy': [], 
    'translat': None, 
    'bugtracker': None}, 
    '_schema': None, 
    '_language': 'en', 
    'origin': 'api', 
    'created_by': {'id': 10, 'username': 'JJMC89'}, 
    'created_date': '2021-10-12T20:26:29.012245Z', 
    'modified_by': {
    'id': 3, 
    'username': 'BD'
    }, 
    'modified_date': np.nan}

You must return the name of the key, because the value is uninformed. You can do with (searching also for nested dict):

nulls = []
    for key in response:
        if isinstance(response[key], dict):
            nested_dict = response[key]
            for key_ in nested_dict:
                if nested_dict[key_] in [np.nan, [], None]:
                    nulls.append(key_)
            
        elif response[key] in [np.nan, [], None]:
            nulls.append(key)
    
      Output:
     ['keywords',
     'subtitle',
     'id',
     'alternates',
     'username',
     'by',
     'sponsor',
     'available_languages',
     'api',
     'feedback',
     'privacy',
     'wid',
     'by',
     'for',
     'icon',
     'ttype',
     'rey',
     'api',
     'user_url',
     'feedback',
     'privacy',
     'translat',
     'bugtracker',
     '_schema',
     'modified_date']
  • Related