Reputation: 5274
I have code that works but I'm wondering if there is a more pythonic way to do this. I have a dictionary and I want to see if:
So in my code the keys of "a", "b", and "c" would succeed, which is correct.
import re
mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":" ",
}
#a,b,c should succeed
for k in mydict.keys():
if k in mydict and mydict[k] is not None and not re.search("^\s*$", str(mydict[k])):
print(k)
else:
print("I am incomplete and sad")
What I have above works, but that seems like an awfully long set of conditions. Maybe this simply is the right solution but I'm wondering if there is a more pythonic "exists and has stuff" or better way to do this?
UPDATE Thank you all for wonderful answers and thoughtful comments. With some of the points and tips, I've updated the question a little bit as there some conditions I didn't have which should also succeed. I have also changed the example to a loop (just easier to test right?).
Upvotes: 20
Views: 35103
Reputation: 91
I see that accepted answer it is a very good point for illustration for None or blank string
personally i think it'd be a simply solution by
mydict.get('a', '')
>>> alpha
mydict.get('k', '')
>>> ''
this would be simple and straightforward.
Upvotes: 0
Reputation: 1646
Here's a simple one-liner to check:
bool(myDict.get("some_key"))
As for checking if the value contains only spaces, you would need to be more careful as None
doesn't have a strip()
method.
Something like this as an example:
try:
exists = bool(myDict.get('some_key').strip())
except AttributeError:
exists = False
Upvotes: 3
Reputation: 140168
Try to fetch the value and store it in a variable, then use object "truthyness" to go further on with the value
v = mydict.get("a")
if v and v.strip():
"a"
is not in the dict, get
returns None
and fails the first condition"a"
is in the dict but yields None
or empty string, test fails, if "a"
yields a blank string, strip()
returns falsy string and it fails too.let's test this:
for k in "abcde":
v = mydict.get(k)
if v and v.strip():
print(k,"I am here and have stuff")
else:
print(k,"I am incomplete and sad")
results:
a I am here and have stuff
b I am incomplete and sad # key isn't in dict
c I am incomplete and sad # c is None
d I am incomplete and sad # d is empty string
e I am incomplete and sad # e is only blanks
if your values can contain False
, 0
or other "falsy" non-strings, you'll have to test for string, in that case replace:
if v and v.strip():
by
if v is not None and (not isinstance(v,str) or v.strip()):
so condition matches if not None
and either not a string (everything matches) or if a string, the string isn't blank.
Upvotes: 25
Reputation: 1147
cond
is a generator function responsible for generating conditions to apply in a short-circuiting manner using the all
function. Given d = cond()
, next(d)
will check if a exists in the dict, and so on until there is no condition to apply, in that case all(d)
will evaluate to True
.
mydict = {
"a":"alpha",
"c":None,
"d":"",
"e":" ",
}
def cond ():
yield 'a' in mydict
yield mydict ['a']
yield mydict ['a'].strip ()
if all (cond ()):
print("I am here and have stuff")
else:
print("I am incomplete and sad")
Upvotes: 0
Reputation: 19154
it check exactly for NoneType
not only None
from types import NoneType # dont forget to import this
mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":" ",
}
#a,b,c should succeed
for k in mydict:
if type(mydict[k]) != NoneType:
if type(mydict[k]) != str or type(mydict[k]) == str and mydict[k].strip():
print(k)
else:
print("I am incomplete and sad")
else:
print("I am incomplete and sad")
Upvotes: 0
Reputation: 1450
Well I have 2 suggestions to offer you, especially if your main issue is the length of the conditions.
The first one is for the check if the key is in the dict. You don't need to use "a" in mydict.keys()
you can just use "a" in mydict
.
The second suggestion to make the condition smaller is to break down into smaller conditions stored as booleans, and check these in your final condition:
import re
mydict = {
"a":"alpha",
"c":None,
"d":"",
"e":" ",
}
inKeys = True if "a" in mydict else False
isNotNone = True if mydict["a"] is not None else False
isValidKey = True if not re.search("^\s*$", mydict["a"]) else False
if inKeys and isNotNone and isValidKey:
print("I am here and have stuff")
else:
print("I am incomplete and sad")
Upvotes: 1
Reputation: 164673
You can use a list comprehension with str.strip
to account for whitespace in strings.
Using if v
is natural in Python to cover False-like objects, e.g. None
, False
, 0, etc. So note this only works if 0 is not an acceptable value.
res = [k for k, v in mydict.items() if (v.strip() if isinstance(v, str) else v)]
['a']
Upvotes: 2
Reputation: 1397
The get method for checking if a key exists is more efficient that iterating through the keys. It checks to see if the key exists without iteration using an O(1)
complexity as apposed to O(n)
. My preferred method would look something like this:
if mydict.get("a") is not None and str(mydict.get("a")).replace(" ", "") != '':
# Do some work
Upvotes: 2