From a list of string, get a list of dictionaries - python

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.

Related

Convert multiple lists into dictionary

I want to convert following
Input: Name;class;subject;grade
sam;4;maths;A
tom;5;science;B
kathy;8;biology;A
nancy;9;maths;B
output: [Name:sam,class:4,subject: maths, grade:A],[name:tom,class:5,subject:science,grade:B],[name: kathy,class:8,subject:biology,grade:B],[name:nancy,class:9,subject:maths,grade:B]
You can create a function that accepts strings in a way that each piece of data is seperated by a character like : or ;.
Then you can use
string.split("the character you used")
to get a list of each piece of data stored in a list.
And finally you can store each of these elements in a dictionary and append that dictionary into the list you want to have as your output.
This code I used in my python shell will help you understand these operations better.
>>> input_string = "Tom:6:Maths"
>>> list_of_elements = input_string.split(":")
>>> container_dictioanry = {"Name":list_of_elements[0], "class":list_of_elements[1], "grade":list_of_elements[2]}
>>> output_list = []
>>> output_list.append(container_dictioanry)
>>> print(output_list)
[{'Name': 'Tom', 'class': '6', 'grade': 'Maths'}]
Basically yours is just a csv text chunk with delimiter ;
It can be as simple as:
input_text = '''<YOUR DATA>'''
lines = input_text.split('\n')
headers = lines[0].split(';')
output = [
dict(zip(headers, line.split(';')))
for line in lines[1:]
]
Since the text is CSV, you can use the csv library.
>>> import csv
>>>
>>>
>>> foo = '''Name;class;subject;grade
... sam;4;maths;A
... tom;5;science;B
... kathy;8;biology;A
... nancy;9;maths;B'''
>>>
>>> reader = csv.DictReader(foo.splitlines(), delimiter=';')
>>> print([row for row in reader])
[{'Name': 'sam', 'class': '4', 'subject': 'maths', 'grade': 'A'}, {'Name': 'tom', 'class': '5', 'subject': 'science', 'grade': 'B'}, {'Name': 'kathy', 'class': '8', 'subject': 'biology', 'grade': 'A'}, {'Name': 'nancy', 'class': '9', 'subject': 'maths', 'grade': 'B'}]

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']}]

How to sort data in the dictionary of list of dictionary in python?

Please help me. I have dataset like this:
my_dict = { 'project_1' : [{'commit_number':'14','name':'john'},
{'commit_number':'10','name':'steve'}],
'project_2' : [{'commit_number':'12','name':'jack'},
{'commit_number':'15','name':'anna'},
{'commit_number':'11','name':'andy'}]
}
I need to sort the dataset based on the commit number in descending order and make it into a new list by ignoring the name of the project using python. The list expected will be like this:
ordered_list_of_dict = [{'commit_number':'15','name':'anna'},
{'commit_number':'14','name':'john'},
{'commit_number':'12','name':'jack'},
{'commit_number':'11','name':'andy'},
{'commit_number':'10','name':'steve'}]
Thank you so much for helping me.
Extract my_dict's values as a list of lists*
Join each sub-list together (flatten dict_values) to form a flat list
Sort each element by commit_number
*list of lists on python2. On python3, a dict_values object is returned.
from itertools import chain
res = sorted(chain.from_iterable(my_dict.values()),
key=lambda x: x['commit_number'],
reverse=True)
[{'commit_number': '15', 'name': 'anna'},
{'commit_number': '14', 'name': 'john'},
{'commit_number': '12', 'name': 'jack'},
{'commit_number': '11', 'name': 'andy'},
{'commit_number': '10', 'name': 'steve'}]
On python2, you'd use dict.itervalues instead of dict.values to the same effect.
Coldspeed's answer is great as usual but as an alternative, you can use the following:
ordered_list_of_dict = sorted([x for y in my_dict.values() for x in y], key=lambda x: x['commit_number'], reverse=True)
which, when printed, gives:
print(ordered_list_of_dict)
# [{'commit_number': '15', 'name': 'anna'}, {'commit_number': '14', 'name': 'john'}, {'commit_number': '12', 'name': 'jack'}, {'commit_number': '11', 'name': 'andy'}, {'commit_number': '10', 'name': 'steve'}]
Note that in the list-comprehension you have the standard construct for flattening a list of lists:
[x for sublist in big_list for x in sublist]
I'll provide the less-pythonic and more reader-friendly answer.
First, iterate through key-value pairs in my_dict, and add each element of value to an empty list. This way you avoid having to flatten out a list of lists:
commits = []
for key, val in my_dict.items():
for commit in val:
commits.append(commit)
which gives this:
In [121]: commits
Out[121]:
[{'commit_number': '12', 'name': 'jack'},
{'commit_number': '15', 'name': 'anna'},
{'commit_number': '11', 'name': 'andy'},
{'commit_number': '14', 'name': 'john'},
{'commit_number': '10', 'name': 'steve'}]
Then sort it in descending order:
sorted(commits, reverse = True)
This will sort based on 'commit_number' even if you don't specify it because it comes alphabetically before 'name'. If you want to specify it for the sake of defensive coding, this would be fastest and cleanest way, to the best of my knowledge :
from operator import itemgetter
sorted(commits, key = itemgetter('commit_number'), reverse = True)

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()).

string to list of dictionaries (python)

I have a string that needs to be split 3 ways and then into a list of dictionaries.
given_string = 'name:mickey,age:58|name:minnie,age:47,weight:60'
data = []
data = [value.split(',') for value in given_string.split('|')]
data = [['name:mickey', 'age:58'], ['name:minnie', 'age:47', 'weight:60']]
Now I want to split this one more time on the ':' and have the data contain a list of two dictionaries so that when I input say data[1][age], I get 47.
Basically, I think I want this for it to work:
data = [{'name': 'mickey', 'age': '58}, {'name': 'minnie', 'age': '47', 'weight': '60'}]
I believe that ultimately, data should be a list of dictionaries but once I split the string into two lists, I get confused in splitting it on the ':' and then converting the sublists to a dictionary.
You can do with a simple list comprehension
>>> [dict(x.split(':') for x in parts.split(','))
for parts in given_string.split('|')]
[{'age': '58', 'name': 'mickey'}, {'age': '47', 'name': 'minnie', 'weight': '60'}]
Nest harder.
>>> [ dict(y.split(':') for y in x.split(',')) for x in 'name:mickey,age:58|name:minnie,age:47,weight:60'.split('|')]
[{'age': '58', 'name': 'mickey'}, {'age': '47', 'name': 'minnie', 'weight': '60'}]
given_string = 'name:mickey,age:58|name:minnie,age:47,weight:60'
data = [value.split(',') for value in given_string.split('|')]
y=[] # make a empty list
for i in data:
z={}
for v in range(len(i)):
b=i[v].split(":") # ['name", "mickey', 'age","58"]
z[b[0]]=b[1] # adding keys and values in dictionary z
y.append(z) # adding dictionary to the list

Categories