How to convert dict to list of dict with python - python

How to convert this dict
"Team":{
"number": '2',
"persons": ['Doe',"john"]
}
to this list of dict
"Team" :[
{"number": '2'},
{ "persons": ['Doe',"john"]}
]
I tried the solutions mentioned in this link but nothing works for me.
Thanks in advance.

That can be done by list comprehension.
def convert(dictionary):
return [{key: value} for key, value in dictionary.items()]
Then, you get
>>> convert({"number": "2", "persons": ["Doe", "John"]})
[{"number": "2"}, {"persons": ["Doe", "John"]}]

Do you mean like this?
let's say it's a single dict
team_dict = {
"number": '2',
"persons": ['Doe',"john"]
}
new_team_dict = [{k: team_dict[k]} for k in team_dict ]

Related

Changing value of a value in a dictionary within a list within a dictionary

I have a json like:
pd = {
"RP": [
{
"Name": "PD",
"Value": "qwe"
},
{
"Name": "qwe",
"Value": "change"
}
],
"RFN": [
"All"
],
"RIT": [
{
"ID": "All",
"IDT": "All"
}
]
}
I am trying to change the value change to changed. This is a dictionary within a list which is within another dictionary. Is there a better/ more efficient/pythonic way to do this than what I did below:
for key, value in pd.items():
ls = pd[key]
for d in ls:
if type(d) == dict:
for k,v in d.items():
if v == 'change':
pd[key][ls.index(d)][k] = "changed"
This seems pretty inefficient due to the amount of times I am parsing through the data.
String replacement could work if you don't want to write depth/breadth-first search.
>>> import json
>>> json.loads(json.dumps(pd).replace('"Value": "change"', '"Value": "changed"'))
{'RP': [{'Name': 'PD', 'Value': 'qwe'}, {'Name': 'qwe', 'Value': 'changed'}],
'RFN': ['All'],
'RIT': [{'ID': 'All', 'IDT': 'All'}]}

Replace text in a list of dictionaries

I have the following sample list of dictionaries and I would like to replace any . in the dictionary with a _, so the list would look like the list below.
I tried using replace but get the following error:
dict object has no attribute 'replace'
if I try something like this:
orig = [
{
"health": "good",
"status": "up",
"date": "2022.03.10",
"device.id": "device01"
},
{
"health": "poor",
"status": "down",
"date": "2022.03.10",
"device.id": "device02"
}
]
length = len(orig)
for i in range(length):
orig[i].replace(".", "_")
Current list:
[
{
"health": "good",
"status": "up",
"date": "2022.03.10",
"device.id": "device01"
},
{
"health": "poor",
"status": "down",
"date": "2022.03.10",
"device.id": "device02"
}
]
The new list should look like this:
[
{
"health": "good",
"status": "up",
"date": "2022_03_10",
"device_id": "device01"
},
{
"health": "poor",
"status": "down",
"date": "2022_03_10",
"device_id": "device02"
}
]
I don't understand how what you're trying would even run. For the line orig[i].replace(".", "_"), orig[i] will be a dict, and since a dict has no replace() method, you'll get an error trying to execute this line.
You need to be working on additional level down, operating on each of the key/value pairs in each dict. Here's one solution:
orig= [{"health": "good", "status": "up", "date":"2022.03.10","device.id":"device01"}, {"health": "poor", "status": "down", "date":"2022.03.10","device.id":"device02"}]
result = []
for inner_dict in orig:
new_inner = {}
for k, v in inner_dict.items():
new_inner[k.replace('.', '_')] = v.replace('.', '_')
result.append(new_inner)
print(result)
If the keys didn't need to change, it would be simpler (see the other two answers that don't get it right). You then wouldn't have to create a new structure, but could just work on the values within the existing structure. But since the keys will also change, it's easiest just to build a new result from scratch, like this shows.
Result:
[{'health': 'good', 'status': 'up', 'date': '2022_03_10', 'device_id': 'device01'}, {'health': 'poor', 'status': 'down', 'date': '2022_03_10', 'device_id': 'device02'}]
Try this:
orig = list(map(lambda item: dict((k.replace('.', '_'), v.replace('.', '_')) for k, v in item.items()), orig))
The output should be your want.
Basically, the original data is a list of dict, and the target is to normalize(replace . -> _) each key and value in the dict.
So the inner transformation is using a dict() to produce a new dict from the original one, dict((k.replace('.', '_'), v.replace('.', '_')) for k, v in item.items())
And for the outer part is a pythonic map operation for iterating a list
Actually, #CryptoFool's answer should be more clear for beginners.
The answer by #CryptoFool seems like the one you want. A slightly more blunt force answer might be to just work with stings.
import json
orig= [
{"health": "good", "status": "up", "date":"2022.03.10","device.id":"device01"},
{"health": "poor", "status": "down", "date":"2022.03.10","device.id":"device02"}
]
orig_new = json.loads(json.dumps(orig).replace(".","_"))
print(orig_new)
That will give you :
[
{'health': 'good', 'status': 'up', 'date': '2022_03_10', 'device_id': 'device01'},
{'health': 'poor', 'status': 'down', 'date': '2022_03_10', 'device_id': 'device02'}
]
The following seems to do the trick:
def convert(list_dict, old_text, new_text):
def replace_dict(old_dict, old_text, new_text):
return {key.replace(old_text, new_text) : val.replace(old_text, new_text) for key, val in old_dict.items()}
for i in range(len(list_dict)):
list_dict[i] = replace_dict(list_dict[i], old_text, new_text)
orig= [{"health": "good", "status": "up", "date":"2022.03.10","device.id":"device01"}, {"health": "poor", "status": "down", "date":"2022.03.10","device.id":"device02"}]
convert(orig, '.', '-')
print(orig)
Basically, it modifies the old dictionary in-place but creates replacement dictionaries for each element.
you need to iterate in list of dictionaries or change format:
# first solution
new_list_of_dictionaries = []
for dictionary in orig:
new_dictionary = {}
for k, v in dictionary.items():
new_dictionary[k.replace(".", "_")] = v.replace(".", "_")
new_list_of_dictionaries.append(new_dictionary)
orig = new_list_of_dictionaries
# second_solution
import json
orig = json.loads(json.dumps(orig).replace(".", "_"))

Python filter nested dict with key value and print a part

Let´s say I have a nested dict like this but much longer:
{
"problems": [{
"1":[{
"name":"asprin abc",
"dose":"",
"strength":"100 mg"
}],
"2":[{
"name":"somethingElse",
"dose":"",
"strenght":"51g"
}],
"3":[{
"name":"againSomethingElse",
"dose":"",
"strenght":"511g"
}],
}],
"labs":[{
"missing_field": "missing_value"
}]
}
Now I want to iterate through the dict and do some filtering. I just want to have the part where the key "name" is LIKE '%aspirin%, as in Transact-SQL.
So the output should be the following:
[{
"name":"asprin abc",
"dose":"",
"strength":"100 mg"
}]
I now how to iterate through the dict but I don´t know how I should achieve the value filtering where I print the whole part where the title matches.
The following is a general solution making no assumption on the structure of the passed object, which could be a list, dictionary, etc. It will recursively descend throug the structure looking for a dictionary with a key "name" whose value contains asprin and will yield that dictionary:
d = {
"problems": [{
"1":[{
"name":"asprin abc",
"dose":"",
"strength":"100 mg"
}],
"2":[{
"name":"somethingElse",
"dose":"",
"strenght":"51g"
}],
"3":[{
"name":"againSomethingElse",
"dose":"",
"strenght":"511g"
}],
}],
"labs":[{
"missing_field": "missing_value"
}]
}
def filter(obj):
if isinstance(obj, list):
for item in obj:
yield from filter(item)
elif isinstance(obj, dict):
if "name" in obj and "asprin" in obj["name"]:
yield obj
else:
for v in obj.values():
if isinstance(v, (list, dict)):
yield from filter(v)
print(list(filter(d)))
Prints:
[{'name': 'asprin abc', 'dose': '', 'strength': '100 mg'}]
Python Demo
I found an easier solution like described above. A list comprehension is much easier
[problem for problem in problem['problems'] if problem['name'].find("aspirin")!=1]
You can try this below:
for p_obj in json_data["problems"]:
for i in p_obj.keys():
for j in p_obj[i]:
if "asprin" in j["name"]:
output.append(j)
print(output)

Create partial dict from recursively nested field list

After parsing a URL parameter for partial responses, e.g. ?fields=name,id,another(name,id),date, I'm getting back an arbitrarily nested list of strings, representing the individual keys of a nested JSON object:
['name', 'id', ['another', ['name', 'id']], 'date']
The goal is to map that parsed 'graph' of keys onto an original, larger dict and just retrieve a partial copy of it, e.g.:
input_dict = {
"name": "foobar",
"id": "1",
"another": {
"name": "spam",
"id": "42",
"but_wait": "there is more!"
},
"even_more": {
"nesting": {
"why": "not?"
}
},
"date": 1584567297
}
should simplyfy to:
output_dict = {
"name": "foobar",
"id": "1",
"another": {
"name": "spam",
"id": "42"
},
"date": 1584567297,
}
Sofar, I've glanced over nested defaultdicts, addict and glom, but the mappings they take as inputs are not compatible with my list (might have missed something, of course), and I end up with garbage.
How can I do this programmatically, and accounting for any nesting that might occur?
you can use:
def rec(d, f):
result = {}
for i in f:
if isinstance(i, list):
result[i[0]] = rec(d[i[0]], i[1])
else:
result[i] = d[i]
return result
f = ['name', 'id', ['another', ['name', 'id']], 'date']
rec(input_dict, f)
output:
{'name': 'foobar',
'id': '1',
'another': {'name': 'spam', 'id': '42'},
'date': 1584567297}
here the assumption is that on a nested list the first element is a valid key from the upper level and the second element contains valid keys from a nested dict which is the value for the first element

merge dictionaries and have one big dictionary within list

payload = [
{
"Beds:": "3"
},
{
"Baths:": "2.0"
},
{
"Sqft:": "1,260"
},
]
How would I have such list be like:
payload = [{'Beds':"3","Baths":"2.0","Sqft":"1,260"}]
instead of multiple dictionaries; I want one dictionary within the list.
Try this:
payload_new = [{i: j[i] for j in payload for i in j}]
This should help. Use the replace method to remove ":"
payload = [
{
"Beds:": "3"
},
{
"Baths:": "2.0"
},
{
"Sqft:": "1,260"
},
]
newDict = [{k.replace(":", ""): v for j in payload for k,v in j.items()}]
print newDict
Output:
[{'Beds': '3', 'Sqft': '1,260', 'Baths': '2.0'}]
Python 3 has built-in dictionary unfolding, try this
payload = {**payload_ for payload_ in payload}
To merge dictionaries in a big dictionary, you can write it this way:
payload={"Beds": 3 ,
"Baths": 2.0,
"Sqft": 1260
}
output:
>>>payload["Baths"]
2.0
views:
using [] was making it a array/list rather than a dictionary.
using "" on keys (e.g: "3") was making them strings instead of integers.

Categories

Resources