I have JSON dictionary something like this:
{'foo': 3, 'bar': 1}
and i want it in JSON array form:
[ { "key": "foo", "value": 3 }, { "key": "bar", "value": 1 }]
What should I do?
You need to iterate over keys and values for this dictionary and then assign the necessary keys in the new dictionary.
import json
input_dict = {'foo': 3, 'bar': 1}
result = []
for k, v in input_dict.items():
result.append({'key': k, 'value': v})
print(json.dumps(result))
And the result:
[{'value': 3, 'key': 'foo'}, {'value': 1, 'key': 'bar'}]
This could be handled with a list comprehension:
import json
json_dict = {'foo': 3, 'bar': 1}
json_array = [ {'key' : k, 'value' : json_dict[k]} for k in json_dict]
print(json.dumps(json_array))
output:
[{"key": "foo", "value": 3}, {"key": "bar", "value": 1}]
Try this (Python 2.7 and above):
json_dict = {'foo': 3, 'bar': 1} # your original dictionary;
json_array = [] # an array to store key-value pairs;
# Loop through the keys and values of the original dictionary:
for key, value in json_dict.items():
# Append a new dictionaty separating keys and values from the original dictionary to the array:
json_array.append({'key': key, 'value': value})
One-liner that does the same thing:
json_array = [{'key': key, 'value': value} for key, value in {'foo': 3, 'bar': 1}.items()]
Hope this helps!
Related
I have a list:
List_ = ["Peter", "Peter", "Susan"]
I want to make a dictonary like this:
Dict_ = {"Name": "Peter", "Count": 2, "Name": "Susan", "Count": 1}
Dict_ = {}
Dict_new = {}
for text in List_:
if text not in Dict_:
Dict_[text] = 1
else:
Dict_[text] += 1
for key, values in Dict_.items():
Dict_new["Name"] = key
Dict_new["Count"] = values
print(Dict_new)
It is printing only last ones:
{"Name": "Susan", "Count": 1}
Here is the implementation that you can use according to what you would like :
from collections import Counter
# Your data
my_list = ["Peter", "Peter", "Susan"]
# Count the occurrences
counted = Counter(my_list)
# Your format
counted_list = []
for key, value in counted.items():
counted_list.append({"Name": key, "Count": value})
print(counted_list)
And output will be :
[{'Name': 'Peter', 'Count': 2}, {'Name': 'Susan', 'Count': 1}]
As noted in comments, a dictionary can only have each key once.
You may want a list of dictionaries, built with help from collections.Counter and a list comprehension.
>>> from collections import Counter
>>> List_ = ["Peter", "Peter", "Susan"]
>>> [{'name': k, 'count': v} for k, v in Counter(List_).items()]
[{'name': 'Peter', 'count': 2}, {'name': 'Susan', 'count': 1}]
In addition to using collections.Counter you could use a defaultdict.
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> for n in List_:
... d[n] += 1
...
>>> d
defaultdict(<class 'int'>, {'Peter': 2, 'Susan': 1})
>>> [{'name': k, 'count': v} for k, v in d.items()]
[{'name': 'Peter', 'count': 2}, {'name': 'Susan', 'count': 1}]
You can use the following code to achieve what you are trying to do.
List_ = ["Peter", "Peter", "Susan"]
dict_ = {}
for name in List_:
if name in dict_:
dict_[name] += 1
else:
dict_[name] = 1
print(dict_)
Generates the following output where key is the name and value is the count.
{'Peter': 2, 'Susan': 1}
data = [{"id": "78ab45",
"name": "Jonh"},
{"id": "69cd234457",
"name": "Joe"}]
I want my function to return the largest value lengths for each key from all dictionaries:
expected_output = [
{ "size": 10, "name": "id" }, #because the length of the largest "id" value is 10
{ "size": 4, "name": "name" }, #because the length of the largest "name" value is 4
]
My code so far:
def my_func(data):
headers_and_sizes = []
for item in data:
for key, value in item.items():
headers_and_sizes.append({"size": f'{len(value)}', "name": key})
if int(headers_and_sizes[0]["size"]) < len(value):
headers_and_sizes[0]["size"] = len(value)
return headers_and_sizes
Gives me this:
[{'size': '6', 'name': 'id'}, {'size': '4', 'name': 'name'}, {'size': '10', 'name': 'id'}, {'size': '3', 'name': 'name'}]
How can I fix that so that it will return the values as in expected_output?
You'll want to be updating a dictionary that stores each key mapped to the maximum length seen for that key thus far.
data = [
{
"id": "78ab45",
"name": "Jonh",
},
{
"id": "69cd234457",
"name": "Joe",
},
]
key_to_max_len = {}
for datum in data:
for key, val in datum.items():
if key not in key_to_max_len or len(val) > key_to_max_len[key]:
key_to_max_len[key] = len(val)
key_size_arr = [{"size": val, "name": key} for key, val in key_to_max_len.items()]
you can get the max value for id and name like below code, and structure the output accordingly
>>> data
[{'id': '78ab45', 'name': 'Jonh'}, {'id': '69cd234457', 'name': 'Joe'}]
id = max(map(lambda x:len(x['id']), data))
name = max(map(lambda x:len(x['name']), data))
>>> id
10
>>> name
4
You can use list comprehension to form a tuple with ids and names:
names_ids = [(eachdict['id'],eachdict['name']) for eachdict in data]
Format the output to have the desired shape (dictionaries), find the max length (using the max() function, passing it the lengths of names and ids, using another list comprehension, inside max()):
expected_output = \
[{"size":max([len(each[0]) for each in names_ids]),"name":"id"},
{"size":max([len(each[1]) for each in names_ids]),"name":"name"}]
Output will be:
[{'name': 'id', 'size': 10}, {'name': 'name', 'size': 4}]
Using the following:
keys = list(data[0].keys())
output = {key:-1 for key in keys}
for d in data:
for k in d.keys():
if len(d[k]) > output[k]:
output[k] = len(d[k])
Will output:
{'id': 10, 'name': 4}
I think the easiest method here is pandas...
import pandas as pd
df = pd.DataFrame(data)
out = [{'size': df['id'].str.len().max(), 'name':'id'},
{'size': df['name'].str.len().max(), 'name':'name'}]
output:
[{'size': 10, 'name': 'id'}, {'size': 4, 'name': 'name'}]
or for addt'l names..
[{'size':df[col].str.len().max(), 'name':col} for col in df.columns]
Here is how you can use a nested dictionary comprehension:
data = [{"id": "78ab45",
"name": "Jonh"},
{"id": "69cd234457",
"name": "Joe"}]
expected_output = [{'size': len(max([i[k] for i in data], key=len)),
'name': k} for k in data[0]]
print(expected_output)
Output:
[{'size': 10, 'name': 'id'},
{'size': 4, 'name': 'name'}]
I want to replace the values (formated as strings) with the same values as integers, whenever the key is 'current_values'.
d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
Desired Output:
d = {'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}
The following piece of code replaces (substrings of) values in a dictionary. It works for nested json structures and copes with json, list and string types. You can easily add other types if needed.
def dict_replace_value(d: dict, old: str, new: str) -> dict:
x = {}
for k, v in d.items():
if isinstance(v, dict):
v = dict_replace_value(v, old, new)
elif isinstance(v, list):
v = list_replace_value(v, old, new)
elif isinstance(v, str):
v = v.replace(old, new)
x[k] = v
return x
def list_replace_value(l: list, old: str, new: str) -> list:
x = []
for e in l:
if isinstance(e, list):
e = list_replace_value(e, old, new)
elif isinstance(e, dict):
e = dict_replace_value(e, old, new)
elif isinstance(e, str):
e = e.replace(old, new)
x.append(e)
return x
# See input and output below
output = dict_replace_value(input, 'string', 'something')
Input:
input = {
'key1': 'a string',
'key2': 'another string',
'key3': [
'a string',
'another string',
[1, 2, 3],
{
'key1': 'a string',
'key2': 'another string'
}
],
'key4': {
'key1': 'a string',
'key2': 'another string',
'key3': [
'a string',
'another string',
500,
1000
]
},
'key5': {
'key1': [
{
'key1': 'a string'
}
]
}
}
Output:
print(output)
{
"key1":"a something",
"key2":"another something",
"key3":[
"a something",
"another something",
[
1,
2,
3
],
{
"key1":"a something",
"key2":"another something"
}
],
"key4":{
"key1":"a something",
"key2":"another something",
"key3":[
"a something",
"another something",
500,
1000
]
},
"key5":{
"key1":[
{
"key1":"a something"
}
]
}
}
d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
for elem in d['datastreams']: # for each elem in the list datastreams
for k,v in elem.items(): # for key,val in the elem of the list
if 'current_value' in k: # if current_value is in the key
elem[k] = int(v) # Cast it to int
print(d)
OUTPUT:
{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}
A general approach (assuming you don't know in advance which key of the dict is pointing to a list) would be to iterate over the dict and check the type of its values and then iterate again into each value if needed.
In your case, your dictionary may contain a list of dictionaries as values, so it is enough to check if a value is of type list, if so, iterate over the list and change the dicts you need.
It can be done recursively with a function like the following:
def f(d):
for k,v in d.items():
if k == 'current_value':
d[k] = int(v)
elif type(v) is list:
for item in v:
if type(item) is dict:
f(item)
>>> d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
>>> f(d)
>>> d
{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}
Can be done with list comprehension:
d['datastreams'] = [{'current_value': int(ds['current_value'])} if ('current_value' in ds) else ds for ds in d['datastreams']]
You can use ast.literal_eval to evaluate the underlying value for items with current_value key in the d['datastreams'] list. Then check whether the type is an int using isinstance for such values. Finally, type cast such values to int.
import ast
d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
for i in d['datastreams']:
for k,v in i.items():
if 'current_value' in k and isinstance(ast.literal_eval(v),int):
i[k] = int(v)
#Output:
print(d)
{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}
You could use this method
which would loop through checks for current_value in list and change it to integer by passing the value through int() function:
for value in d.values():
for element in value:
if 'current_value' in element:
element['current_value'] = int(element['current_value'])
Taking alec_djinn's solution little farther to handle also nested dicts:
def f(d):
for k,v in d.items():
if k == 'current_value':
d[k] = int(v)
elif type(v) is list:
for item in v:
if type(item) is dict:
f(item)
if type(v) is dict:
f(v)
This question already has answers here:
Update value of a nested dictionary of varying depth
(28 answers)
Closed 4 years ago.
I have two dictionaries, the first is what the default values of the second one should fall back to if they are not present or not defined, and it is somewhat like this:
default_dict = {
'lorem': {
'foo': 'white',
'bar': 'black',
},
'ipsum': {
'xyz': '',
'abc': {},
'qwe': {}
}
}
And the second looks like this:
custom_dict = {
'lorem': {
'bar': 'blue',
},
'ipsum': {
'xyz': 'apple',
'qwe': { 'one': 'strawberry' }
}
}
Is there any way I can "update" from the default_dict with the values from the custom_dict?
The desired result would look something like this:
custom_dict = {
'lorem': {
'foo': 'white',
'bar': 'blue',
},
'ipsum': {
'xyz': 'apple',
'abc': {},
'qwe': { 'one': 'strawberry' }
}
}
I've tried doing default_dict.update(custom_dict) and then custom_dict = default_dict, but as you can imagine I'm just getting custom_dict back untouched... So the keys of default_dict are getting removed when it is updated.
Use:
d={a:b for k,v in custom_dict.items() for a,b in v.items()}
print({k:{a:d.get(a,b) for a,b in v.items()} for k,v in default_dict.items()})
A dictionary comprehension + a nested dictionary comprehension would work.
Output:
{'lorem': {'foo': 'white', 'bar': 'blue'}, 'ipsum': {'xyz': 'apple', 'abc': {}, 'qwe': {'one': 'strawberry'}}}
if the structure of your dictionaries are always like above so the following code works fine:
for item in default_dict:
for value in default_dict[item].keys():
if value not in custom_dict[item].keys():
custom_dict[item].update({value: default_dict[item][value]})
good luck
I want to merge the contents of the following two dictionaries
>>> key_dict
{
'1': 'seq',
'0': 'seq',
'2': 'seq'
}
>>> value_dict
{
'tedious; repetitive and boring': 'text',
'worldly': 'text',
'ordinary': 'text'
}
Such that in the final list I have something like
>>>final_list
[
{
'seq': 0,
'text': 'worldly'
},
{
'seq': 1,
'text': 'tedious; repetitive and boring'
},
{
'seq': 2,
'text': 'ordinary'
}
]
EDIT:
Apologies, I tried this
>>> final_list = []
>>> temp_dict = {}
>>> for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
... temp_dict[value1] = key1
... temp_dict[value2] = key2
... final_list.append[temp_dict]
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: 'builtin_function_or_method' object is not subscriptable
>>>
Any help on where am I going wrong
Edit 2:
After correcting, final_list.append[temp_dict] to final_list.append(temp_dict)
I get this
>>> pprint(final_list)
[{'seq': '1', 'text': 'ordinary'},
{'seq': '1', 'text': 'ordinary'},
{'seq': '1', 'text': 'ordinary'}]
>>>
Can somebody explain why the values are getting repeated, I am not able to comprehend that.
You are actually on the right track. Values are repeating because you don't empty temp_dict at the end of each iteration. In fact, you don't even need temp_dict at all, just do:
>>> for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
... final_list.append({value1: int(key1), value2: key2})
[{'seq': 1, 'text': 'ordinary'},
{'seq': 0, 'text': 'tedious; repetitive and boring'},
{'seq': 2, 'text': 'worldly'}]
If order matters, then you should use collections.OrderedDict instead of normal a dict.
With the order as specified in the question
from collections import OrderedDict
from pprint import pprint
key_dict = {
'1': 'seq',
'0': 'seq',
'2': 'seq'
}
value_dict = {
'tedious; repetitive and boring': 'text',
'worldly': 'text',
'ordinary': 'text'
}
kds = OrderedDict(sorted(kv for kv in key_dict.items()))
vds = OrderedDict(sorted((kv for kv in value_dict.items()), reverse=True))
d = [{v1: int(k1), v2: k2} for (k1, v1), (k2, v2) in zip(kds.items(), vds.items())]
pprint(d)
Output:
[{'seq': 0, 'text': 'worldly'},
{'seq': 1, 'text': 'tedious; repetitive and boring'},
{'seq': 2, 'text': 'ordinary'}]
The issue with your original code could have been resolved by moving temp_dict inside the loop.
e.g.
final_list = []
for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
temp_dict = {}
temp_dict[value1] = key1
temp_dict[value2] = key2
final_list.append(temp_dict)