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']}]
Related
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)
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.
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.
I have this:
query='id=10&q=7&fly=none'
and I want to split it to create a dictionary like this:
d = { 'id':'10', 'q':'7', 'fly':'none'}
How can I do it with little code?
By splitting twice, once on '&' and then on '=' for every element resulting from the first split:
query='id=10&q=7&fly=none'
d = dict(i.split('=') for i in query.split('&'))
Now, d looks like:
{'fly': 'none', 'id': '10', 'q': '7'}
In your case, the more convenient way would be using of urllib.parse module:
import urllib.parse as urlparse
query = 'id=10&q=7&fly=none'
d = {k:v[0] for k,v in urlparse.parse_qs(query).items()}
print(d)
The output:
{'id': '10', 'q': '7', 'fly': 'none'}
Note, that urlparse.parse_qs() function would be more useful if there multiple keys with same value in a query string. Here is an example:
query = 'id=10&q=7&fly=none&q=some_identifier&fly=flying_away'
d = urlparse.parse_qs(query)
print(d)
The output:
{'q': ['7', 'some_identifier'], 'id': ['10'], 'fly': ['none', 'flying_away']}
https://docs.python.org/3/library/urllib.parse.html#urllib.parse.parse_qs
This is what I came up with:
dict_query = {}
query='id=10&q=7&fly=none'
query_list = query.split("&")
for i in query_list:
query_item = i.split("=")
dict_query.update({query_item[0]: query_item[1]})
print(dict_query)
dict_query returns what you want. This code works by splitting the query up into the different parts, and then for each of the new parts, it splits it by the =. It then updates the dict_query with each new value. Hope this helps!
If I have for instance the file:
;;;
;;;
;;;
A 1 2 3
B 2 3 4
C 3 4 5
And I want to read it into a dictionary of {str: list of str} :
{'A': ['1', '2', '3'], 'B': ['2', '3', '4'], 'C': ['3', '4', '5']
I have the following code:
d = {}
with open('file_name') as f:
for line in f:
while ';;;' not in line:
(key, val) = line.split(' ')
#missingcodehere
return d
What should I put in after the line.split to assign the keys and values as a str and list of str?
To focus on your code and what you are doing wrong.
You are pretty much in an infinite loop with your while ';;;' not in line. So, you want to change your logic with how you are trying to insert data in to your dictionary. Simply use a conditional statement to check if ';;;' is in your line.
Then, when you get your key and value from your line.strip().split(' ') you simply just assign it to your dictionary as d[key] = val. However, you want a list, and val is currently a string at this point, so call split on val as well.
Furthermore, you do not need to have parentheses around key and val. It provides unneeded noise to your code.
The end result will give you:
d = {}
with open('new_file.txt') as f:
for line in f:
if ';;;' not in line:
key, val = line.strip().split(' ')
d[key] = val.split()
print(d)
Using your sample input, output is:
{'C': ['3', '4', '5'], 'A': ['1', '2', '3'], 'B': ['2', '3', '4']}
Finally, to provide an improvement to the implementation as it can be made more Pythonic. We can simplify this code and provide a small improvement to split more generically, rather than counting explicit spaces:
with open('new_file.txt') as fin:
valid = (line.split(None, 1) for line in fin if ';;;' not in line)
d = {k:v.split() for k, v in valid}
So, above, you will notice our split looks like this: split(None, 1). Where we are providing a maxsplit=1.
Per the docstring of split, it explains it pretty well:
Return a list of the words in S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
Finally, we simply use a dictionary comprehension to obtain our final result.
Why not simply:
def make_dict(f_name):
with open(f_name) as f:
d = {k: v.split()
for k, v in [line.strip().split(' ')
for line in f
if ';;;' not in line]}
return d
Then
>>> print(make_dict('file_name'))
{'A': ['1', '2', '3'], 'B': ['2', '3', '4'], 'C': ['3', '4', '5']}