Python - How to unpack key with key,value pair? - python

Anyone can help and explain how to unpack items from key with many key,value pair?
{'jsonrpc': '2.0', 'result': [{'userid': '8', 'clock': '1644715846', 'action': '3', 'resourceid': '0'}], 'id': '1'}
I need transform 'result' to dictionary.
# Print type 'dict'
print(type(result2))
#Print type 'list'
print(type(result2['result']))
output = []
# Here i get error
for key_value in result2['result']:
key, value = key_value.split(': ', 1)
if not output or key in output[-1]:
output.append({})
output[-1][key] = value
print(output)
"""
key, value = key_value.split(': ', 1)
AttributeError: 'dict' object has no attribute 'split'
"""
Thank you in advance

As clearly result2['result'] is a list but that list contains the dict which you want.
So to get that simply unpack this list and get the frst element;
result2['result'][0]

result2['result'] is a list of dicts. To iterate over the list, you can do for result in result2['result'] To iterate over each resulting dict, you can do for key, value in result.items().
result2 = {'jsonrpc': '2.0', 'result': [{'userid': '8', 'clock': '1644715846', 'action': '3', 'resourceid': '0'}], 'id': '1'}
output = [{}]
for result in result2['result']:
for key, value in result.items():
if key in output[-1]:
output.append({})
output[-1][key] = value
print(output)
# [{'userid': '8', 'clock': '1644715846', 'action': '3', 'resourceid': '0'}]
This code goes to a lot of trouble to iterate through each dictionary and accumulate a list of new dictionaries for the apparent purpose of combining dictionaries with disjoint sets of keys, but for this particular input, or any other input where each dictionary in result has the same keys, or any input where there's only one dictionary, there's no point in iterating over the dictionaries at all. You could just as easily do:
output = result2['result']
print(output)
# [{'userid': '8', 'clock': '1644715846', 'action': '3', 'resourceid': '0'}]
to get the same exact output with none of the work.

Related

create a specific python dictionary from 2 lists

I have the following data:
fsm_header = ['VLAN_ID', 'NAME', 'STATUS']
fsm_results = [['1', 'default', 'active'],
['2', 'VLAN0002', 'active'],
['3', 'VLAN0003', 'active']]
I want to create a specific dictionary like this:
{'VLAN_ID':['1','2','3'],
'NAME':['default','VLAN0002','VLAN0003'],
'STATUS':['active','active','active']}
I'm having trouble finding the right combination, as the one I'm using:
dict(zip(fsm_header, row)) for row in fsm_results
gives me another type of useful output, but not the one I mentioned above.
I would prefer to see something without using the zip function, but even with zip is ok.
You need to unpack and zip fsm_results too:
out = {k:list(v) for k,v in zip(fsm_header, zip(*fsm_results))}
Output:
{'VLAN_ID': ['1', '2', '3'],
'NAME': ['default', 'VLAN0002', 'VLAN0003'],
'STATUS': ['active', 'active', 'active']}
If you don't mind tuple as values; then you could use:
out = dict(zip(fsm_header, zip(*fsm_results)))
Output:
{'VLAN_ID': ('1', '2', '3'),
'NAME': ('default', 'VLAN0002', 'VLAN0003'),
'STATUS': ('active', 'active', 'active')}
You could also write the same thing using dict.setdefault:
out = {}
for lst in fsm_results:
for k, v in zip(fsm_header, lst):
out.setdefault(k, []).append(v)

From a list of string, get a list of dictionaries

I have a list of strings which contains spanish-recipesĀ“s ingredients and its quantities and I would like to get a list of dictionaries splitting every ingredient, unit and quantity.
This is the list:
ingredients=[
'50',
'ccs',
'aceite',
'1',
'hoja',
'laurel',
'\n',
'1',
'cabeza',
'ajos',
'1',
'vaso',
'vino',
'1,5',
'kilos',
'conejo',
'\n',
...]
I would like to get a dict like this:
my_dic=[
{"name":"aceite" ,"qt":50 ,"unit": "ccs"},
{"name":"laurel" ,"qt":1 ,"unit": "hoja"},
{"name":"ajos" ,"qt":1 ,"unit": "cabeza"},
{"name":"vino" ,"qt":1 ,"unit": "vaso"},
{"name":"conejo" ,"qt":1,5 ,"unit": "kilos"},
...]
I have been trying things but it was all a disaster.
Any ideas?
Thanks in advance!!
So first, you want to remove the newlines from your original list:
ingredients = [i for i in ingredients if i is not '\n']
Then, each ingredient name is every third element in the ingredients list starting from the third element. Likewise for the quantity and unit, starting from the second and first elements, respectively:
names = ingredients[2::3]
units = ingredients[1::3]
qts = ingredients[::3]
Then, iterate through these lists and construct the data structure you specified (which is not actually a dict but a list of dicts):
my_list = []
for i in range(len(names)):
my_dict = {"name":names[i],"qt":qts[i],"unit":units[i]}
my_list.append(my_dict)
There are a lot of ways to compress all of the above, but I have written it for comprehensibility.
This doesn't produce a dictionary, but it does give you the output that you specify in the question:
# Strip out the \n values (can possibly do this with a .strip() in the input stage)
ingredients = [value for value in ingredients if value != '\n']
labels = ['qt', 'unit', 'name']
my_dic = [dict(zip(labels, ingredients[i:i+3])) for i in range(0, len(ingredients), 3)]
my_dic contains:
[{'qt': '50', 'unit': 'ccs', 'name': 'aceite'},
{'qt': '1', 'unit': 'hoja', 'name': 'laurel'},
{'qt': '1', 'unit': 'cabeza', 'name': 'ajos'},
{'qt': '1', 'unit': 'vaso', 'name': 'vino'},
{'qt': '1,5', 'unit': 'kilos', 'name': 'conejo'}]
You can clean you list with filter to remove the \n characters and then zip() it together to collect your items together. This makes a quick two-liner:
l = filter(lambda w: w != '\n', ingredients)
result = [{'name': name, 'qt':qt, 'unit': unit}
for qt, unit, name in zip(l, l, l)]
result:
[{'name': 'aceite', 'qt': '50', 'unit': 'ccs'},
{'name': 'laurel', 'qt': '1', 'unit': 'hoja'},
{'name': 'ajos', 'qt': '1', 'unit': 'cabeza'},
{'name': 'vino', 'qt': '1', 'unit': 'vaso'},
{'name': 'conejo', 'qt': '1,5', 'unit': 'kilos'}]
How about:
ingredients = (list)(filter(lambda a: a != '\n', ingredients))
ing_organized = []
for i in range (0, len(ingredients) , 3):
curr_dict = {"name": ingredients[i+2] ,"qt": ingredients[i] ,"unit": ingredients[i+1]}
ing_organized.append(curr_dict)
I just removed '\n' elements from the list as they didn't seem to have meaning.

How to filter a list in a dictionary by the key and values?

I got a very big dictionary with lists in it called traffic. Here is a small example of my dictionary:
{'redlights': [{'id': 32,
'userid': '3',
'time': '2013-09-T17:12:00+05:00',
'calls': 1,
'crossings': '0',
'bad_behaviour': '0',
'senior': False,
'cat': False,
'dog': True,
'hitrun': 'David Williams'},
{'id': 384,
So, I called it hello as a test. I want all the keys within the list redlights that has 'senior' in it with value 'False'. I first tried this dict comprehension to get all the keys with senior in it:
hello = traffic['redlights']
new = {key: value for key, value in hello.items() if key == senior}
But then I got this error: AttributeError: 'list' object has no attribute 'items'
Probably because it's a list, but I don't know how I can get the keys that has senior in it with the value false. It has to be in the redlights list because the other lists are not relevant. How do I do this in a dict comprehension?
hello is not a dictionary, it's a list (of dictionaries) and lists don't have items. You have to iterate over each of the dictionaries in the list.
This example will get the id of each dictionary with senior=False.
res = [d['id'] for d in hello if not d['senior']]

Grouping values to a list in dict

While reading a csv file using csv.DictReader
I get
[{'id': 1, 'status1': '1', 'status2': '2', 'status3': '3' }]
How can I manuplate while reading or later to get:
[{'id': 1, 'status': ['1', '2', '3']}]
TLDR;
I want to group similar fields into a list.
and/or - how can i do this in pandas pd.read_csv() too?
Thanks in advance!
If it is certain that the only fields you want to group are those who end with digits, you can use a regex to identify them, and append their corresponding values to a list:
import re
def compact_dict(d):
compact = {}
for key, value in d.items():
# a group containing anything, followed by at least one digit
m = re.match(r'(.*)\d+', key)
if m:
# the key that we use is the original one without the final digits
compact.setdefault(m.group(1), []).append(value)
else:
# not part of a group of similar keys, we just store the key:value pair
compact[key] = value
return compact
data = [{'id': 1, 'status1': '1', 'status2': '2', 'status3': '3' }]
out = [compact_dict(d) for d in data]
print(out)
# [{'id': 1, 'status': ['1', '2', '3']}]

String to dict conversion

I want to convert string in dictionary and my string is as follow
order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508&order_status=Success&failure_message=&payment_mode=Net Banking&card_name=AvenuesTest&status_code=null&status_message=Y&currency=INR&amount=100.0&billing_name=test&billing_address=test&billing_city=Pune&billing_state=Maharashtra&billing_zip=411041&billing_country=India&billing_tel=1234567890&billing_email=test#gmail.com&delivery_name=test&delivery_address=test&delivery_city=Pune&delivery_state=Maharashtra&delivery_zip=411041&delivery_country=India&delivery_tel=1234567890&merchant_param1=3&merchant_param2=&merchant_param3=&merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&mer_amount=100.0&eci_value=null&retry=N&response_code=0&billing_notes=&trans_date=17/03/2017 11:27:30&bin_country=
You can use split method to split this string:
c="order_id=BW_225996&tracking_id=306003083135"
print {p.split("=")[0]:p.split("=")[1] for p in c.split("&")}
Output:
{'order_id': 'BW_225996', 'tracking_id': '306003083135'}
You can try:
>>> s = """order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508&order_status=Success&failure_message=&payment_mode=Net Banking&card_name=AvenuesTest&status_code=null&status_message=Y&currency=INR&amount=100.0&billing_name=test&billing_address=test&billing_city=Pune&billing_state=Maharashtra&billing_zip=411041&billing_country=India&billing_tel=1234567890&billing_email=test#gmail.com&delivery_name=test&delivery_address=test&delivery_city=Pune&delivery_state=Maharashtra&delivery_zip=411041&delivery_country=India&delivery_tel=1234567890&merchant_param1=3&merchant_param2=&merchant_param3=&merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&mer_amount=100.0&eci_value=null&retry=N&response_code=0&billing_notes=&trans_date=17/03/2017 11:27:30"""
>>> s_list = s.split("&")
>>> s_list
['order_id=BW_225996', 'tracking_id=306003083135', 'bank_ref_no=1489730168508', 'order_status=Success', 'failure_message=', 'payment_mode=Net Banking', 'card_name=AvenuesTest', 'status_code=null', 'status_message=Y', 'currency=INR', 'amount=100.0', 'billing_name=test', 'billing_address=test', 'billing_city=Pune', 'billing_state=Maharashtra', 'billing_zip=411041', 'billing_country=India', 'billing_tel=1234567890', 'billing_email=test#gmail.com', 'delivery_name=test', 'delivery_address=test', 'delivery_city=Pune', 'delivery_state=Maharashtra', 'delivery_zip=411041', 'delivery_country=India', 'delivery_tel=1234567890', 'merchant_param1=3', 'merchant_param2=', 'merchant_param3=', 'merchant_param4=', 'merchant_param5=', 'vault=N', 'offer_type=null', 'offer_code=null', 'discount_value=0.0', 'mer_amount=100.0', 'eci_value=null', 'retry=N', 'response_code=0', 'billing_notes=', 'trans_date=17/03/2017 11:27:30']
>>> s_dict = {}
>>> for data in s_list:
s_dict[data.split("=")[0]] = data.split("=")[1]
>>> print s_dict
{'billing_tel': '1234567890', 'status_code': 'null', 'delivery_country': 'India', 'delivery_name': 'test', 'currency': 'INR', 'delivery_city': 'Pune', 'billing_country': 'India', 'billing_notes': '', 'retry': 'N', 'billing_email': 'test#gmail.com', 'billing_zip': '411041', 'billing_name': 'test', 'merchant_param5': '', 'order_status': 'Success', 'status_message': 'Y', 'mer_amount': '100.0', 'merchant_param3': '', 'merchant_param2': '', 'delivery_zip': '411041', 'card_name': 'AvenuesTest', 'delivery_tel': '1234567890', 'billing_address': 'test', 'order_id': 'BW_225996', 'eci_value': 'null', 'offer_code': 'null', 'merchant_param4': '', 'payment_mode': 'Net Banking', 'offer_type': 'null', 'discount_value': '0.0', 'delivery_address': 'test', 'billing_city': 'Pune', 'merchant_param1': '3', 'response_code': '0', 'failure_message': '', 'bank_ref_no': '1489730168508', 'amount': '100.0', 'trans_date': '17/03/2017 11:27:30', 'tracking_id': '306003083135', 'vault': 'N', 'delivery_state': 'Maharashtra', 'billing_state': 'Maharashtra'}
A simple loop could fix this:
a='order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508&order_status=Success&failure_message=&payment_mode=Net Banking&card_name=AvenuesTest&status_code=null&status_message=Y&currency=INR&amount=100.0&billing_name=test&billing_address=test&billing_city=Pune&billing_state=Maharashtra&billing_zip=411041&billing_country=India&billing_tel=1234567890&billing_email=test#gmail.com&delivery_name=test&delivery_address=test&delivery_city=Pune&delivery_state=Maharashtra&delivery_zip=411041&delivery_country=India&delivery_tel=1234567890&merchant_param1=3&merchant_param2=&merchant_param3=&merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&mer_amount=100.0&eci_value=null&retry=N&response_code=0&billing_notes=&trans_date=17/03/2017 11:27:30&bin_country='
dic={}
[dic.update({e.split('=')[0] : e.split('=')[1]}) for e in a.split('&')]
_str="order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508&order_status=Success&failure_message=&payment_mode=Net Banking&card_name=AvenuesTest&status_code=null&status_message=Y&currency=INR&amount=100.0&billing_name=test&billing_address=test&billing_city=Pune&billing_state=Maharashtra&billing_zip=411041&billing_country=India&billing_tel=1234567890&billing_email=test#gmail.com&delivery_name=test&delivery_address=test&delivery_city=Pune&delivery_state=Maharashtra&delivery_zip=411041&delivery_country=India&delivery_tel=1234567890&merchant_param1=3&merchant_param2=&merchant_param3=&merchant_param4=&merchant_param5=&vault=N&offer_type=null&offer_code=null&discount_value=0.0&mer_amount=100.0&eci_value=null&retry=N&response_code=0&billing_notes=&trans_date=17/03/2017 11:27:30&bin_country="
{a:b for a,b in [i.split("=") for i in _str.split('&')]}
Please try this simple code, this will produce your required output,
input_string = 'order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508'
splitted_string = input_string.split('&')
final_output = {}
for items in splitted_string:
dic_values = items.split('=')
final_output[dic_values[0]] = dic_values[1]
print final_output
Output:
{'order_id': 'BW_225996', 'tracking_id': '306003083135', 'bank_ref_no': '1489730168508'}
Initially we are splitting the string using '&'.
Then we are splitting every items in list using '=' as the dictionary key and
values.
Please let me know interms of any queries.
Here is a function that will do the job for you. It performs the following operations:
Break the given string into a list of strings representing key-value pairs.
Split each string representation of a key-value pair into a key and its associated value.
Insert each key and it's associated value into a dict.
parse_dict
def parse_dict(string):
dictionary = dict()
key_value_pairs = string.split('&')
for pair in key_value_pairs:
key, value = pair.split('=')
dictionary[key] = value
return dictionary
Example usage:
parsed_dict = parse_dict("order_id=BW_225996&tracking_id=306003083135")
print(parsed_dict)
Output:
{'order_id': 'BW_225996', 'tracking_id': '306003083135'}
I hope this answers your question. Happy coding!
Since this question is tagged django, this is the shortest and most correct solution:
from django.http import QueryDict
query_string = 'order_id=BW_225996&tracking_id=306003083135&bank_ref_no=1489730168508'
qdict = QueryDict(query_string) # dict like object
Unlike the other solutions, this deals with url encoding and multiple values per key automatically (use getlist()).

Categories