check if dictionary key has empty value
Asked Answered
P

6

6

I have the following dictionary

dict1 ={"city":"","name":"yass","region":"","zipcode":"",
       "phone":"","address":"","tehsil":"", "planet":"mars"}

I am trying to create a new dictionary that will be based on dict1 but,

  1. it will not contain keys with empty strings.
  2. it will not contain those keys that I dont want to include.

i have been able to fulfill the requirement 2 but getting problem with requirement 1. Here is what my code looks like.

dict1 ={"city":"","name":"yass","region":"","zipcode":"",
   "phone":"","address":"","tehsil":"", "planet":"mars"}

blacklist = set(("planet","tehsil"))    
new = {k:dict1[k] for k in dict1 if k not in blacklist} 

this gives me the dictionary without the keys: "tehsil", "planet" I have also tried the following but it didnt worked.

new = {k:dict1[k] for k in dict1 if k not in blacklist and dict1[k] is not None}

the resulting dict should look like the one below:

new = {"name":"yass"}
Prentice answered 22/5, 2013 at 13:59 Comment(0)
C
4

This would have to be the fastest way to do it (using set difference):

>>> dict1 = {"city":"","name":"yass","region":"","zipcode":"",
       "phone":"","address":"","tehsil":"", "planet":"mars"}
>>> blacklist = {"planet","tehsil"}
>>> {k: dict1[k] for k in dict1.viewkeys() - blacklist if dict1[k]}
{'name': 'yass'}

White list version (using set intersection):

>>> whitelist = {'city', 'name', 'region', 'zipcode', 'phone', 'address'}
>>> {k: dict1[k] for k in dict1.viewkeys() & whitelist if dict1[k]}
{'name': 'yass'}
Cronyism answered 22/5, 2013 at 14:4 Comment(4)
Thanks for that. what will be the solution if I only want non empty white list values?Prentice
@yasra002 added that as wellCronyism
Which option is better using sets that I used or the one one that you used. I am pretty new to python so I am not sure which one is the best one.Prentice
@yasra002 People only wrote sets like set((1, 2, 3)) back in Python <= 2.6 when there was no set literal({1, 2, 3}). What you are doing is creating a tuple and passing it to a set constructor. Nowadays we have set literals so you should use them ;)Cronyism
G
5

This is a white list version:

>>> dict1 ={"city":"","name":"yass","region":"","zipcode":"",
       "phone":"","address":"","tehsil":"", "planet":"mars"}
>>> whitelist = ["city","name","planet"]
>>> dict2 = dict( (k,v) for k, v in dict1.items() if v and k in whitelist )
>>> dict2
{'planet': 'mars', 'name': 'yass'}

Blacklist version:

>>> blacklist = set(("planet","tehsil"))
>>> dict2 = dict( (k,v) for k, v in dict1.items() if v and k not in blacklist )
>>> dict2
{'name': 'yass'}

Both are essentially the same expect one has not in the other in. If you version of python supports it you can do:

>>> dict2 = {k: v for k, v in dict1.items() if v and k in whitelist}

and

>>> dict2 = {k: v for k, v in dict1.items() if v and k not in blacklist}
Gaullism answered 22/5, 2013 at 14:1 Comment(1)
may as well use a dictionary comprehension {k: v for k, v ....}, even though it's not Python 2.6 compatible like this, we know OP is using 2.7+Cronyism
C
4

This would have to be the fastest way to do it (using set difference):

>>> dict1 = {"city":"","name":"yass","region":"","zipcode":"",
       "phone":"","address":"","tehsil":"", "planet":"mars"}
>>> blacklist = {"planet","tehsil"}
>>> {k: dict1[k] for k in dict1.viewkeys() - blacklist if dict1[k]}
{'name': 'yass'}

White list version (using set intersection):

>>> whitelist = {'city', 'name', 'region', 'zipcode', 'phone', 'address'}
>>> {k: dict1[k] for k in dict1.viewkeys() & whitelist if dict1[k]}
{'name': 'yass'}
Cronyism answered 22/5, 2013 at 14:4 Comment(4)
Thanks for that. what will be the solution if I only want non empty white list values?Prentice
@yasra002 added that as wellCronyism
Which option is better using sets that I used or the one one that you used. I am pretty new to python so I am not sure which one is the best one.Prentice
@yasra002 People only wrote sets like set((1, 2, 3)) back in Python <= 2.6 when there was no set literal({1, 2, 3}). What you are doing is creating a tuple and passing it to a set constructor. Nowadays we have set literals so you should use them ;)Cronyism
W
1

You're on the right track. Consider:

Python 2.7.3 (default, Apr 24 2012, 00:00:54) 
[GCC 4.7.0 20120414 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> dict1 ={"city":"","name":"yass","region":"","zipcode":"",
...    "phone":"","address":"","tehsil":"", "planet":"mars"}
>>> 
>>> def isgood(undesired, key, val): return key not in undesired and key and val
... 
>>> dict([x for x in dict1.items() if isgood(["planet", "tehsil"], *x)])
{'name': 'yass'}
Waxman answered 22/5, 2013 at 14:3 Comment(2)
@lshpeck but this will only work for the fixed length dictionary? Correct me if Iam wrong?Prentice
No, this will work for any length dictionary. (true both before and after my edit)Waxman
H
1

Simply test dict1[k] for Truth value (instead of is None.).

new = {k:dict1[k] for k in dict1 if k not in blacklist and dict1[k]}
Husband answered 22/5, 2013 at 14:7 Comment(0)
B
1

Testing if the value is not an empty string is not done using is not None.

An empty string evaluates as False, while any non-empty string evaluates as True. Hence, you can test it directly, and simply remove the is not None from your expression :

new = {k:dict1[k] for k in dict1 if k not in blacklist and dict1[k]}
Bema answered 22/5, 2013 at 14:30 Comment(0)
L
0

dict2 = { (k,v) for k,v in dict1.items() if ( k in whitelist ) and ( v != "" ) }

Leffen answered 10/3 at 13:34 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Oby

© 2022 - 2024 — McMap. All rights reserved.