Related
I have a json like this :
[
{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"more": { "sd": 2, "fg": 5, "ef": 6 },
"s": 6,
"as": 8,
"dfd": [{ "sda": "something", "SX": ["CB"], "jhgjh": "", "das": "" }]
},
{
"a3": 1,
"b": 2,
"c": 3,
"ds": 4,
"more": { "sd": 32, "fg": 5, "3ef": 6 },
"s": 6,
"as": 38,
"dfd": [
{ "sda": "somethinDDDg", "SX": ["CDB"], "jhgjh": "1", "das": "wes" }
]
}
]
I am trying to loop over all levels and convert the json into a specific format. I json can have any number of key value pairs and levels. Key value pairs can be different for each json entry.
I tried using for loop on key value pair and was able to get it converted into the required format on first level of json. I am unable to expand it to any level (where level is not fixed).
Expected output :
'data' : [{
{
'name' : 'a',
'value':1
},
{
'name' : 'b',
'value': 2
},
{
'name' : 'c',
'value': 3
},
{
'name' : 'd',
'value': 4
},
{
'name' : 'more',
'value': {'name' :'sd',
'value': 2},
{'name' : 'fg',
'value' : 5},
{'name':'ef',
'value':6},
{
'name' : 's',
'value': 6
},
{
'name' : 'as',
'value':
},
{
'name' : 'dfd',
'value': [ {"sda": "something",
"SX":["CB"],
"jhgjh": "",
"das": ''
}]
},
{{
'name' : 'a3',
'value':1
},
{
'name' : 'b',
'value': 2
},
{
'name' : 'c',
'value': 3
},
{
'name' : 'ds',
'value': 4
},
{
'name' : 'more',
'value': {'name' :'sd',
'value': 32},
{'name' : 'fg',
'value' : 5},
{'name':'3ef',
'value':6},
{
'name' : 's',
'value': 6
},
{
'name' : 'as',
'value': 38
},
{
'name' : 'dfd',
'value': [ {"sda": "somethinDDDg",
"SX":["CDB"],
"jhgjh": "1",
"das": 'wes'
}]
}}]
Okay, I think I understand now what you want. Using a recursive helper function:
def names_and_values(d):
if type(d) != dict:
return d
return [{"name": key, "value": names_and_values(value)} for key, value in d.items()]
And the json module from the standard library:
import json
data = json.loads(your_json_string)
converted_data = [names_and_values(d) for d in data]
Output:
[[{'name': 'a', 'value': 1},
{'name': 'b', 'value': 2},
{'name': 'c', 'value': 3},
{'name': 'd', 'value': 4},
{'name': 'more',
'value': [{'name': 'sd', 'value': 2},
{'name': 'fg', 'value': 5},
{'name': 'ef', 'value': 6}]},
{'name': 's', 'value': 6},
{'name': 'as', 'value': 8},
{'name': 'dfd',
'value': [{'sda': 'something',
'SX': ['CB'],
'jhgjh': '',
'das': ''}]}],
[{'name': 'a3', 'value': 1},
{'name': 'b', 'value': 2},
{'name': 'c', 'value': 3},
{'name': 'ds', 'value': 4},
{'name': 'more',
'value': [{'name': 'sd', 'value': 32},
{'name': 'fg', 'value': 5},
{'name': '3ef', 'value': 6}]},
{'name': 's', 'value': 6},
{'name': 'as', 'value': 38},
{'name': 'dfd',
'value': [{'sda': 'somethinDDDg',
'SX': ['CDB'],
'jhgjh': '1',
'das': 'wes'}]}]]
I have a json array on python which I want to filter based on the value of : my_json_array['models']['variants']['condition']['type']
my json array looks like the following :
my_json_array = [
{'id': 1,
'models': [
{'color': {'code': '#626262', 'name': 'Gray'},
'variants': [{'id': 1,
'condition': [{'id': 1,
'type': 'type1',
'value': 14900},
{'id': 2,
'type': 'type2',
'value': 14000}]]
]
}]
I'm looking for a method to remove condition items with type = type2. The output should look like this :
my_json_array = [{
'id': 1,
'models': [
{'color': {'code': '#626262', 'name': 'Gray'},
'variants': [{'id': 1,
'condition': [{'id': 1,
'type': 'type1',
'value': 14900}]]
]
}]
Do you mean this?
my_json_array = [
{
'id': 1,
'models': [
{
'color': {'code': '#626262', 'name': 'Gray'},
'variants': [
{
'id': 1,
'condition': [
{
'id': 1,
'type': 'type1',
'value': 14900
},
{
'id': 2,
'type': 'type2',
'value': 14000
}
]
}
]
}
]
}
]
for mydict in my_json_array:
for model in mydict['models']:
for variant in model['variants']:
for condition in variant['condition']:
if condition['type']=="type2":
variant['condition'].remove(condition)
print(my_json_array) # [{'id': 1, 'models': [{'color': {'code': '#626262', 'name': 'Gray'}, 'variants': [{'id': 1, 'condition': [{'id': 1, 'type': 'type1', 'value': 14900}]}]}]}]
Given I have a list of dictionaries I want to create new list of lists grouping the dictionaries by the values of "price":
dicts = [
{ "name": "item1", "price": 10 },
{ "name": "item2", "price": 5 },
{ "name": "item3", "price": 10 },
{ "name": "item4", "price": 12 },
{ "name": "item5", "price": 12 },
{ "name": "item6", "price": 5 }
]
Should create:
grouped_dicts = [
[{ "name": "item1", "price": 10 },
{ "name": "item3", "price": 10 }],
[{ "name": "item2", "price": 5 },
{ "name": "item6", "price": 5 }],
[{ "name": "item4", "price": 12 },
{ "name": "item5", "price": 12 }]
]
Is there a nice way of doing this?
Thanks
As an alternative to the answer above, here is how you do it without an additional import:
d = {}
for item in dicts:
d.setdefault(item['price'], []).append(item)
list(d.values())
Out:
[[{'name': 'item1', 'price': 10}, {'name': 'item3', 'price': 10}],
[{'name': 'item2', 'price': 5}, {'name': 'item6', 'price': 5}],
[{'name': 'item4', 'price': 12}, {'name': 'item5', 'price': 12}]]
You could use deaultdict
from collections import defaultdict
d=defaultdict(list)
for item in dicts:
d[list(item.values())[-1]].append(item)
Output:
defaultdict(list,
{10: [{'name': 'item1', 'price': 10},
{'name': 'item3', 'price': 10}],
5: [{'name': 'item2', 'price': 5}, {'name': 'item6', 'price': 5}],
12: [{'name': 'item4', 'price': 12},
{'name': 'item5', 'price': 12}]})
If you just need the list then just extract the values of defaultdict
list(d.values())
Output:
[[{'name': 'item1', 'price': 10}, {'name': 'item3', 'price': 10}],
[{'name': 'item2', 'price': 5}, {'name': 'item6', 'price': 5}],
[{'name': 'item4', 'price': 12}, {'name': 'item5', 'price': 12}]]
I have following list of dictionaries which contains job_name,count and city name
question = [{
"count": 2,
"city": "Pune",
"job_NAME": "clerk"
}, {
"count": 1,
"city": "kolkata",
"job_NAME": "manager"
}, {
"count": 2,
"city": "Mumbai",
"job_NAME": "accountant"
}, {
"count": 1,
"city": "New Delhi",
"job_NAME": "clerk"
}]
what i want is if job_name is same in this case "clerk" the count and city has to be in one list under key "jobs"
answer = [{
"job_name": "clerk",
"jobs": [{
"city": "pune",
"count": 2
}, {
"city": "New Delhi",
"count": 1
}]
}, {
"job_name": "manager",
"jobs": [{
"city": "kolkata",
"count": 1
}]
}, {
"job_name": "accountant",
"jobs": [{
"city": "Mumbai",
"count": 2
}]
}]
if there is any job duplicate job profile in question list in this case clerk its city and count should be appended in "jobs" key list.
i would be very grateful for any help provided!
Thanks in advance
Using collections.defaultdict
Ex:
from collections import defaultdict
d = defaultdict(list)
question = [{'count': 2, 'city': 'Pune', 'job_NAME': 'clerk'}, {'count': 1, 'city': 'kolkata', 'job_NAME': 'manager'}, {'count': 2, 'city': 'Mumbai', 'job_NAME': 'accountant'}, {'count': 1, 'city': 'New Delhi', 'job_NAME': 'clerk'}]
for i in question:
d[i["job_NAME"]].append({"city": i["city"], "count": i["count"]})
answer = [{"job_name": k, "jobs": v} for k, v in d.items()]
print(answer)
Output:
[{'job_name': 'clerk',
'jobs': [{'city': 'Pune', 'count': 2}, {'city': 'New Delhi', 'count': 1}]},
{'job_name': 'accountant', 'jobs': [{'city': 'Mumbai', 'count': 2}]},
{'job_name': 'manager', 'jobs': [{'city': 'kolkata', 'count': 1}]}]
I use defaultdict(list) to group the entries from the input list first and then in a second iteration I setup the result:
from collections import defaultdict
groups = defaultdict(list)
for jobs in question:
job_name = jobs["job_NAME"]
del jobs["job_NAME"]
groups[job_name].append(jobs)
answer = [
dict(job_name=job_name, jobs=jobs) for job_name, jobs in groups.items()
]
# alternative with classic loop
answer = []
for job_name, jobs in groups.items():
answer.append(dict(job_name=job_name, jobs=jobs))
One-liner:
from itertools import groupby
from operator import itemgetter
answer = [{'job_name': k, 'jobs': [{f: v for f, v in d.items() if f != 'job_NAME'} for d in g]}
for k, g in groupby(sorted(question, key=itemgetter('job_NAME')), key=itemgetter('job_NAME'))]
Result:
[{'job_name': 'accountant', 'jobs': [{'count': 2, 'city': 'Mumbai'}]},
{'job_name': 'clerk',
'jobs': [{'count': 2, 'city': 'Pune'}, {'count': 1, 'city': 'New Delhi'}]},
{'job_name': 'manager', 'jobs': [{'count': 1, 'city': 'kolkata'}]}]
Sort and group question by job_NAME and then just construct answer as list of dicts with job_name and jobs.
I'm trying to script a simple Character Generator that I can use for Pen and Paper RPG's. I was thinking about storing all my information in a nested dictionary and saving it into a JSON file.
However, while creating the following dictionary, I receive as error:
nhashable type: 'dict', focussing on {'cha': 1}}}
core_phb = {
'races': {
'Human': {
{'abilities': 'None'},
{'alignment': 'Neutral'},
{'size': 'Medium'},
{'speed': 6},
{'languages': 'Common'},
{'ability_modifiers': {
{'str': 1},
{'dex': 1},
{'con': 1},
{'int': 1},
{'wis': 1},
{'cha': 1}}}
},
'Dwarf': {
{'abilities': [
'ability1',
'ability2'
]},
{'alignment': 'Lawful Good'},
{'size': 'Medium'},
{'speed': 5},
{'languages': [
'Common',
'Dwarven'
]},
{'ability_modifiers': [
{'con': 2},
{'wis': 1}
]}
},
'Elf': {
{'abilities': [
'ability1',
'ability2'
]},
{'alignment': 'Chaotic Good'},
{'size': 'Medium'},
{'speed': 6},
{'languages': [
'Common',
'Elven'
]},
{'ability_modifiers': [
{'dex': 2},
{'int': 1}
]}
}
},
'classes': {
{'Fighter': {}},
{'Ranger': {}},
{'Wizard': {}}
},
'ability_scores': [
{'Str': 'str'},
{'Dex': 'dex'},
{'Con': 'con'},
{'Int': 'int'},
{'Wis': 'wis'},
{'Cha': 'cha'}]
}
I am simply trying to create the dictionary, not calling any keys from it.
As I understand from TypeError: unhashable type: 'dict' , I can use frozenset() to get keys.
Is there a better way to do what I am trying to do?
You seem to be making dictionaries {...} incorrectly for Python.
Lists look like this:
[ {'a': 1}, {'b': 1}, {'c': 1} ]
Dictionaries look like this:
{ 'a': 1, 'b': 2, 'c': 3 }
If I'm guessing the behavior you want correctly, then you probably wanted something like this:
human = {
'abilities': 'None',
'alignment': 'Neutral',
'size': 'Medium',
'speed': 6,
'languages': 'Common',
'ability_modifiers': {
'str': 1,
'dex': 1,
'con': 1,
'int': 1,
'wis': 1,
'cha': 1
}
}
The problem is not with the dicts, but with the sets. The elements of a set must be hashable. In
core_phb = {
'races': {
'Human': {
{'abilities': 'None'},
{'alignment': 'Neutral'},
{'size': 'Medium'},
{'speed': 6},
{'languages': 'Common'},
{'ability_modifiers': {
{'str': 1},
{'dex': 1},
{'con': 1},
{'int': 1},
{'wis': 1},
{'cha': 1}}}
},
'Dwarf': {
{'abilities': [
'ability1',
'ability2'
]},
{'alignment': 'Lawful Good'},
{'size': 'Medium'},
{'speed': 5},
{'languages': [
'Common',
'Dwarven'
]},
{'ability_modifiers': [
{'con': 2},
{'wis': 1}
]}
},
'Elf': {
{'abilities': [
'ability1',
'ability2'
]},
{'alignment': 'Chaotic Good'},
{'size': 'Medium'},
{'speed': 6},
{'languages': [
'Common',
'Elven'
]},
{'ability_modifiers': [
{'dex': 2},
{'int': 1}
]}
}
},
'classes': {
{'Fighter': {}},
{'Ranger': {}},
{'Wizard': {}}
},
'ability_scores': [
{'Str': 'str'},
{'Dex': 'dex'},
{'Con': 'con'},
{'Int': 'int'},
{'Wis': 'wis'},
{'Cha': 'cha'}]
}
the key is fine, but the value is an illegal set, because its elements are dicts. You could make frozensets from the sets and you'd be OK.
{frozenset({1})}
{frozenset({1})}
{{1}}
Traceback (most recent call last):
Python Shell, prompt 7, line 1
builtins.TypeError: unhashable type: 'set'
I think this :
'Human': {
{'abilities': 'None'},
{'alignment': 'Neutral'},
{'size': 'Medium'},
{'speed': 6},
{'languages': 'Common'},
{'ability_modifiers': {
{'str': 1},
{'dex': 1},
{'con': 1},
{'int': 1},
{'wis': 1},
{'cha': 1}}}
},
should be a list. Otherwise, each of the comma-separated elements is a mutable element which you are trying to store in a set. You are already doing it right with the very last entry:
'ability_scores': [
{'Str': 'str'},
{'Dex': 'dex'},
{'Con': 'con'},
{'Int': 'int'},
{'Wis': 'wis'},
{'Cha': 'cha'}]
so why not all the others?