Python Iterating in a dictionary to get empty key's - python

Hello guys I'm trying to iterate from a dictionary to get the keys in case some of keys would be empty, but I have no idea how to achieve this.
Any idea ?
def val(**args):
args = args
print args
# print args
# print (args.keys())
val(name = '', country = 'Canada', phone = '')
Whit this example I got {'country': 'Canada', 'name': '', 'phone': ''} but when I'm really looking is to get only the keys of the empty keys in a list using append, the problem is that it gives me all the keys when and not just the empty keys.
In that case I would like to return something like this:
name, phone
I appreciate your help.

Iterate the dictionary and extract keys where the value is an empty string:
empty_keys = [k for k, v in args.items() if v == '']
or as a function:
>>> def val(**args):
... return [k for k, v in args.items() if v == '']
...
>>> val(name = '', country = 'Canada', phone = '')
['phone', 'name']

This is how you get a list of the empty keys:
empty = [k for k, v in args.items() if not v or v.isspace()]
Notice that the above includes the cases when the value is None or '' or only spaces.

The for statement can be used to iterate over the key/values of a dictionary, then you can do what you want with them.
def val(args) :
outputList = []
for k, v in args :
if v == '' :
outputList.append(k)
return outputList
This function will return a list made up of the keys whose value are the empty string.

Related

Reformating a dictionary of list based on items in another list

I have a dictionary of lists like
source = {"name":["hans","james","mat"],"country":["spain"],"language":["english","french"]}
and another list like
data_not_avail = ["hans","spain","mat"]
How is it possible to reformat source dictionary into the following format
{
"exist":{"name":["james"], "language":["english","french"]},
"not_exist":{"name":["hans","mat"], "country":["spain"]}
}
I was trying to solve by finding the key of item which are present in list but it was not a success
data_result = {}
keys_list = []
for v in data_not_avail:
keys = [key for key, value in source.items() if v in value]
data_result.update({keys[0]:[v]})
keys_list.extend(keys)
This is a approach, you can use a list comprehension (or python built in filter) to filter every element within source lists with the content of data_not_avail.
data = {"exist": {}, "not_exist": {}}
for key, value in source.items():
data["exist"][key] = [v for v in value if v not in data_not_avail]
data["not_exist"][key] = [v for v in value if v in data_not_avail]
# if you dont need empty list in the result
if not data["exist"][key]:
del data["exist"][key]
if not data["not_exist"][key]:
del data["not_exist"][key]
Naive way of solving it is this, check it out.
values = list(source.values())
exist_values = []
not_values = []
for l in values:
temp_exist = []
temp_not = []
for item in l:
if item not in data_not_avail:
temp_exist.append(item)
else:
temp_not.append(item)
exist_values.append(temp_exist)
not_values.append(temp_not)
exist = {}
not_exist = {}
keys = ['name', 'language', 'country']
for i,key in enumerate(keys):
if len(exist_values[i]) != 0:
exist[key] = exist_values[i]
if len(not_values[i]) != 0:
not_exist[key] = not_values[i]
print(exist, not_exist)
#{'name': ['james'], 'country': ['english', 'french']}
#{'name': ['hans', 'mat'], 'language': ['spain']}

Python: Replace a specific word in value of dictionary

I have a dictionary
a = {'url' : 'https://www.abcd.com'}
How to use replace and removed 'https://www.' and just be 'abcd.com'?
I tried
a = [w.replace('https://www.', '') for w in a]
But it only return the key. Thanks!
If your dictionary has more entries:
a_new = {k:v.replace('https://www.', '') for k,v in a.items()]
You access the values of the dictionary using: a['url']
and then you update the string value of url using the replace function:
a['url'] = a['url'].replace('https://www.', '')
There is nothing to iterate on, just retrieve the key, modify it, and save it
a = {'url': 'https://www.abcd.com'}
a['url'] = a['url'].replace('https://www.', '')
print(a) # {'url': 'abcd.com'}
The syntax for dict comprehension is slightly different:
a = {key: value.replace('https://www.', '') for key, value in a.items()}
As per documentation: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
And https://docs.python.org/3/tutorial/datastructures.html#looping-techniques for dict.items().
if you want your result to be a dictionary:
a = {k: v.replace('https://www.', '') for k, v in a.items()}
if you want your result to be an array:
a = [v.replace('https://www.', '') for v in a.values()]
More on dictionary comprehension here: https://www.python.org/dev/peps/pep-0274/

Get a specific value from a list of dictionaries

I want to get the value a specific value '1222020' which has 'Expiration' as a key:
The 'Expiration' key can be placed at any position.
input :
my_list=[{'Key': 'Expiration', 'Value': '12122020'}, {'Key': 'Name', 'Value': 'Config Test 2'}]
my solution:
res = [sub['Value'] for sub in my_list if sub['Key'] =='Expiration' ]
print(res)
Sometimes the tag 'Expiration' is not present.
How to Handle that and avoid NoneType Object error
If you could re-organize your data like so,
custom_dict = {'Expiration': '12122020', 'Name': 'Config Test 2'}
Then, you could write the code like this,
def get_key_value_from_dictionary_search(dict_data, key_search_phrase, value_search_phrase):
for k,v in dict_data.items():
if k is key_search_phrase and v is value_search_phrase:
return k, v
_k, _v = get_key_value_from_dictionary_search(custom_dict, "Expiration", "12122020")
print("Key : {}\nValue : {}".format(_k, _v))
If the Expiration key isn't present, your res evaluates to an empty list. So if you just check for the presence on an empty list, you'll know if Expiration was in there to begin with.
def get_result(lst, default="99999999"):
res = [sub['Value'] for sub in lst if sub['Key'] == 'Expiration']
if res:
# there is something in the list, so return the first thing
return res[0]
else:
# the list is empty, so Expiration wasn't in lst
return default
print(get_result(my_list))

JSON formatting by appending dict values to list

I have a JSON object which is like this:
{ "produktNr:"1234",
"artNr_01":"12",
"artNr_02":"23",
"artNr_03":"",
"artNr_04":"14",
"name_01":"abc",
"name_02":"der",
"test":"junk"
}
I would like to convert this into a dictionary like this:
{ "produktNr:"1234", "artNr":["12","23","","14"], "name":["abc","der"], "test":"junk"}
This conversion is based on a sequence given say, seq = ["artNr","name"]. So the contents of the sequence are searched in the dictionary's keys and the values collected into a list.
My attempt so far:
tempDict = {}
for key,value in fmData.iteritems():
for seqval in seq:
if seqval in key:
if seqval in tempDict:
tempDict[seqval].append(value)
else:
x = []
x.append(value)
tempDict[seqval]=x
else:
tempDict[key] = value
faces a few problems.
The list of values are not ordered i.e, "artNr":["","14","12","23"]
instead of values of [_01,_02,_03,_04]
The items cannot be popped from the dictionary since in the loop the dictionary items cannot be deleted resulting in:
{ "produktNr:"1234", "artNr":["12","23","","14"],"artNr_01":"12", "artNr_02":"23", "artNr_03":"","artNr_04":"14","name":["abc","der"],"name_01":"abc", "name_02":"der", "test":"junk"}
Would love to understand how to deal with this, especially if there's a pythonic way to solve this problem.
You may use OrderedDict from the collections package:
from collections import OrderedDict
import re
input_dict = { "produktNr":"1234",
"artNr_01":"12",
"artNr_02":"23",
"artNr_03":"",
"artNr_04":"14",
"name_01":"abc",
"name_02":"der",
"test":"junk" }
# split keys on the first '_'
m = re.compile('^([^_]*)_(.*)')
def _order_by( item ):
# helper function for ordering the dict.
# item is split on first '_' and, if it was successful
# the second part is returned otherwise item is returned
# if key is something like artNr_42, return 42
# if key is something like test, return test
k,s = item
try:
return m.search(k).group(2)
except:
return k
# create ordered dict using helper function
orderedDict = OrderedDict( sorted(input_dict.items(), key=_order_by))
aggregated_dict = {}
for k, v in orderedDict.iteritems():
# split key
match = m.search(k)
if match:
# key is splittable, i.e., key is something like artNr_42
kk = match.group(1)
if kk not in aggregated_dict:
# create list and add value
aggregated_dict[kk] = [v]
else:
# add value
aggregated_dict[kk].append(v)
else:
# key is not splittable, i.e., key is something like produktNr
aggregated_dict[k] = v
print(aggregated_dict)
which gives the desired output
{'produktNr': '1234', 'test': 'junk', 'name': ['abc', 'der'], 'artNr': ['12', '23', '', '14']}
You can recreate a new dictionary that will group values of keys with '_' in the keys in a list while the other keys and values are kept intact. This should do:
d = { "produktNr":"1234", "artNr_01":"12", "artNr_02":"23","artNr_03":"","artNr_04":"14","name_01":"abc","name_02":"der","test":"junk"}
new_d= {}
for k, v in d.items():
k_new = k.split('_')[0]
if '_' in k:
if k_new not in new_d:
new_d[k_new] = [v]
else:
new_d[k_new].append(v)
else:
new_d[k_new] = v
print(new_d)
# {'artNr': ['', '14', '23', '12'], 'test': 'junk', 'produktNr': '1234', 'name': ['der', 'abc']}
Dicts are unordered collections, so the order with which the values are appended to the list will be indeterminate.
A slight modification of your code:
tempDict = {}
for key,value in fmData.iteritems():
seqval_in_key = "no"
for seqval in seq:
if seqval in key:
seqval_in_key = "yes"
for seqval in seq:
if seqval in key:
if seqval in tempDict:
tempDict[seqval].append(value)
else:
x = []
x.append(value)
tempDict[seqval]=x
else:
if (seqval_in_key == "no"):
tempDict[key] = value
print tempDict
Result:
{'produktNr': '1234', 'test': 'junk', 'name': ['abc', 'der'], 'artNr': ['14', '23', '', '12']}

Removing nested dict items with dict comprehension

I have two dicts:
blocked = {'-5.00': ['121', '381']}
all_odds = {'-5.00': '{"121":[1.85,1.85],"381":[2.18,1.73],"16":[2.18,1.61],"18":\
[2.12,1.79]}'}
I want to first check whether the .keys() comparision (==) returns True, here it does (both -5.00) then I want to remove all items from all_odds that has the key listed in blocked.values() .
For the above it should result in:
all_odds_final = {'-5.00': '{"16":[2.18,1.61],"18": [2.12,1.79]}'}
I tried for loop:
if blocked.keys() == all_odds.keys():
for value in blocked.values():
for v in value:
for val in all_odds.values():
val = eval(val)
if val.has_key(v):
del val[v]
which you know is very ugly plus it's not working properly yet.
First, make the string a dictionary with ast.literal_eval(). Don't use eval():
>>> import ast
>>> all_odds['-5.00'] = ast.literal_eval(all_odds['-5.00'])
Then you can use a dictionary comprehension:
>>> if blocked.keys() == all_odds.keys():
... print {blocked.keys()[0] : {k:v for k, v in all_odds.values()[0].iteritems() if k not in blocked.values()[0]}}
...
{'-5.00': {'18': [2.12, 1.79], '16': [2.18, 1.61]}}
But if you want the value of -5.00 as a string...
>>> {blocked.keys()[0]:str({k: v for k, v in all_odds.values()[0].iteritems() if k not in blocked.values()[0]})}
{'-5.00': "{'18': [2.12, 1.79], '16': [2.18, 1.61]}"}
Here's how you can do the same in about 2 lines. I'm not going to use ast, or eval here, but you can add that if you want to use that.
>>> blocked = {'-5.00': ['121', '381']}
>>> all_odds = {'-5.00': {'121':[1.85,1.85],'381':[2.18,1.73],'16':[2.18,1.61],'18':\
... [2.12,1.79]}}
>>> bkeys = [k for k in all_odds.keys() if k in blocked.keys()]
>>> all_odds_final = {pk: {k:v for k,v in all_odds.get(pk).items() if k not in blocked.get(pk)} for pk in bkeys}
>>> all_odds_final
{'-5.00': {'18': [2.12, 1.79], '16': [2.18, 1.61]}}
This seems to work:
blocked = {'-5.00': ['121', '381']}
all_odds = {'-5.00': {"121":[1.85,1.85],"381":[2.18,1.73],"16":[2.18,1.61],"18":\
[2.12,1.79]}}
all_odds_final = dict(all_odds)
for key, blocks in blocked.iteritems():
map(all_odds_final[key].pop,blocks,[])
If you do not want to copy the dictionary, you can just pop items out of the original all_odds dictionary:
for key, blocks in blocked.iteritems():
map(all_odds[key].pop,blocks,[])
The empty list in the map function is so pop gets called with None as it's second argument. Without it pop only gets one argument and will return an error if the key is not present.

Categories

Resources