def mergeDict(object):
dict1 = {}
for i in range(len(object)):
dict1.update({'id': object[i].id, 'name': object[i].name, 'age': object[i].age, 'location': object[i].location})
return dict1
merged_dict = mergeDict(details_sorted)
But this doesn't work.
I want to get something like this:
{1: {'id': 1, 'name': 'John', 'age': '25'; 'location': 'somewhere'},
2: {'id': 2, 'name': ......}}
It looks like the return statement is in the for loop, which means it will only ever return the update of the first dict.
You don't want to update the dict; you just want to insert a value on key i. Also, the return goes after the for, not in it. Here is a modified version:
def mergeDict(object):
dict1 = {}
for i in range(len(object)):
dict1[i] = {'id': object[i].id, 'name': object[i].name, 'age': object[i].age, 'location': object[i].location}
return dict1
merged_dict = mergeDict(details_sorted)
Your update version would have updated the id, name, age and location keys of dict1 -- and you don't want that. You want to update the id key of dict1 with another dictionary containing the keys id, name, age and location.
Do a bit of experiment.
def mergeDict(object):
dict1 = {}
dict1.update({'id': 'object[i].id', 'name': 'object[i].name', 'age': 'object[i].age', 'location': 'object[i].location'})
dict1.update({'id': 'object[j].id', 'name': 'object[j].name', 'age': 'object[j].age', 'location': 'object[j].location'})
return dict1
merged_dict = mergeDict(None)
print merged_dict
Output:
{'name': 'object[j].name', 'age': 'object[j].age', 'location': 'object[j].location', 'id': 'object[j].id'}
Errors:
Only last object values are retained as the keys are same for all objects. So the for loop has no effect.
It's like saying
x = {}
x['k'] = y
x['k'] = z
There is only one key - k and it's latest value is z
One-liner in Python 3.0:
merged_dict = {i: dict(id=o.id, name=o.name, age=o.age, location=o.location)
for i, o in enumerate(details_sorted)}
If the result keys are consecutive integers, why not a list instead of dict?
merged = [ dict(id=o.id, name=o.name, age=o.age, location=o.location)
for i, o in enumerate(details_sorted) ]
A list has the added benefit of preserving sort order.
Related
I am working with django and got back a response that looks like this
Name,surname
AVA,AAJ
DAA2,ASA
EAA23,VVD
GAA43,DDA
AAA42,AAS
MAA21,JJ
produced by this code
#api_view(["POST"])
def testfunc(request):
if request.method == 'POST':
x = request.body.decode('utf-8')
print(x)
return JsonResponse(x,safe=False)
i want to place this into a dictionary with the first row being the key and the remaining rows being the values, so they can be further processed.
You need to first split the text in lines and then split words in each line.
Something like this:
lines = x.strip().split("\n")
keys = lines[0].split(",")
users_list = []
for line in lines[1:]:
d = dict()
for i, val in enumerate(line.strip().split(",")):
d[keys[i]] = val
users_list.append(d)
example output:
>>> print(users_list)
[{'Name': 'AVA', 'surname': 'AAJ'}, {'Name': 'DAA2', 'surname': 'ASA'}, {'Name': 'EAA23', 'surname': 'VVD'}, {'Name': 'GAA43', 'surname': 'DDA'}, {'Name': 'AAA42', 'surname': 'AAS'}, {'Name': 'MAA21', 'surname': 'JJ'}]
I have a dict as follows.
dict = {'P': ['Demo'], 'Q': ['PMS']}
And I have a list of Dict as follows.
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
I need to have the dict's respective value in all as bellow.
new_list = [{'Name': 'PMS','Code': 'Q'}, {'Name': 'Demo','Code': 'P'}]
In this specific case, given that the values are just strings and therefore hashable objects, you can use a dictionary of reverse mappings. Be aware that it could not be used if the values were not hashable.
dct = {'P': ['Demo'], 'Q': ['PMS']}
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
reverse_mapping = {v[0]:k for k, v in dct.items()}
new_list = [d.copy() for d in all]
for d in new_list:
d['Code'] = reverse_mapping[d['Name']]
print(new_list)
This gives:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
dct = {'P': ['Demo'], 'Q': ['PMS']}
all_ = [{'Name': 'PMS'}, {'Name': 'Demo'}]
out = [dict(**l, Code=next(k for k, v in dct.items() if l['Name'] in v)) for l in all_]
print(out)
Prints:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
Or: you can make temporary dictionary:
tmp = {v[0]:k for k, v in dct.items()}
out = [dict(**l, Code=tmp[l['Name']]) for l in all_]
print(out)
You could make an inverted dictionary of codes, then go through the list of dictionaries and add the codes in:
codes = {"P": ["Demo"], "Q": ["PMS"]}
lst = [{"Name": "PMS"}, {"Name": "Demo"}]
inverted_codes = {value: key for key, values in codes.items() for value in values}
# {'Demo': 'P', 'PMS': 'Q'}
for dic in lst:
code = dic["Name"]
dic["Code"] = inverted_codes[code]
print(lst)
Output
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
I have a list of dictionaries that looks like the following:
data = [{'Name': 'Paul', 'Date': '20200412', 'ID': '1020'}, {'Name': 'Frank', 'Date': '20200413', 'ID': '1030'}, {'Name': 'Anna', 'Date': '20200414', 'ID': '1040'}]
I need to create a new list of dictionaries, where ID's value would be the key, and the value is another dictionary with key/values associated with this specific ID.
This is the desired output:
new_data = [{'1020': {'Name': 'Paul', 'Date': '20200412'}},
{'1030': {'Name': 'Frank', 'Date': '20200413'}},
{'1040': {'Name': 'Anna', 'Date': '20200414'}}]
I have tried:
for index, my_dict in enumerate(data):
new_data = []
key = my_dict['ID']
new_data.append(key)
But that only assigned the key value, not sure how to push it into into a new dict along with other key/values.
>>> [{i['ID']: {k:v for k,v in i.items() if k != 'ID'}} for i in data]
[{'1020': {'Name': 'Paul', 'Date': '20200412'}},
{'1030': {'Name': 'Frank', 'Date': '20200413'}},
{'1040': {'Name': 'Anna', 'Date': '20200414'}}]
new_data = []
for index, my_dict in enumerate(data):
key = my_dict['ID']
del my_dict['ID']
new_data.append({key:data[index]})
To add the other values you simply need to create a new dict like this:
new_data.append( key:{
'name':my_dict['name']
'Date':my_dict['date']
}
You also don't need to make the 'key' variable, you can just use 'my_dict['ID']'
You could try this list comprehension:
[{x["ID"]: {k: v for k, v in x.items() if k != "ID"}} for x in data]
Which assigns ID as the parent key to the dictionary, and filters out the ID key from the child dictionary inside a dict comprehension
Which could be broken down into this:
result = []
for x in data:
result.append({x["ID"]: {k: v for k, v in x.items() if k != "ID"}})
And even to a straightforward loop approach:
result = []
for x in data:
dic = {x["ID"]: {}}
for k, v in x.items():
if k != "ID":
dic[x["ID"]][k] = v
result.append(dic)
Output:
[{'1020': {'Name': 'Paul', 'Date': '20200412'}}, {'1030': {'Name': 'Frank', 'Date': '20200413'}}, {'1040': {'Name': 'Anna', 'Date': '20200414'}}]
I would like to know how I can change a value in a dictionary using list of keys and 1 value
my_dict = {
'bob': {
'name': {'first': 'FirstName', 'last': 'LastName'},
'job': 'Developer'
}
}
string1 = 'bob.name.first=Bob'
string1 = string.split('=')
string2 = string1[0].split('.')
string2.append(string[1])
Here I end up with a list of 4 items, the first 3 are keys and the last is the value.
How can I use this given list to change the value in my_dict considering that the given list keys number can be changed for example if I want to change bob.job=QA
You can write:
string1 = 'bob.name.first=Bob'
string1,string2 = string1.split('=')
string1 = string1.split('.')
my_dict[string1[0]][string1[1]][string1[2]] = string2
I suppose the following function is what you are looking for, it works with any number of keys and creates intermediates dictionaries if not exist yet.
d = {
'bob': {
'name': {
'first': 'FirstName',
'last': 'LastName'
},
'job': 'Developer'
}
}
def update_dict_by_expr(d, expr):
keys_value = expr.split('=')
keys = keys_value[0].split('.')
value = keys_value[1]
item = d
while len(keys) > 1:
key = keys.pop(0)
if key not in item:
item[key] = {}
item = item[key]
key = keys[0]
item[key] = value
print(d)
update_dict_by_expr(d, 'bob.name.first=Bob Junior')
update_dict_by_expr(d, 'bob.name.birth.date=01/01/2017')
update_dict_by_expr(d, 'bob.name.birth.place=NYC')
print(d)
You want a dict with keys that can be accessed as attributes. You can achieve that by subclassing dict class, and add support for your need. I think this is more pythonic solution as it is much more intuative:
class MyDict(dict):
def __getattr__(self, attr):
return self[attr] if attr in self.keys() else None
def __setattr__(self, attr, value):
self[attr] = value
my_dict = MyDict({
'bob': MyDict(
{'name':
MyDict({'first': 'FirstName', 'last': 'LastName'}),
'job':'Developer'})})
>>> my_dict.bob
{'job': 'Developer', 'name': {'last': 'LastName', 'first': 'FirstName'}}
>>> my_dict.bob.job
'Developer'
>>> my_dict.bob.name
{'last': 'LastName', 'first': 'FirstName'}
It does require some overhead, as you will need to build your dicts based on MyDict. Regular dicts won't work if added to this dict.
This supports setting a new value as well:
>>> my_dict.bob.job = 'QA'
>>> my_dict.bob.job
'QA'
If you want to update Bob's job you can access it using my_dict['bob']['job']
my_dict = {
'bob': {
'name': {'first': 'FirstName', 'last': 'LastName'},
'job': 'Developer'
}
}
my_dict['bob']['job'] = 'QA'
print(my_dict)
>> {'bob': {'name': {'last': 'LastName', 'first': 'FirstName'}, 'job': 'QA'}}
or by splitting your string:
my_dict = {
'bob': {
'name': {'first': 'FirstName', 'last': 'LastName'},
'job': 'Developer'
}
}
bobjob_key_value = 'bob.job=QA'
key, value = bobjob_key_value.split('=')
key = key.split('.')
my_dict[key[0]][key[1]] = value
print(my_dict)
>> {'bob': {'job': 'QA', 'name': {'last': 'LastName', 'first': 'FirstName'}}}
import yaml
def get_dictionary_replace_value(file, new_value, strip_qoutes=True):
with open(file, 'r') as rf:
yaml_doc = yaml.load(rf)
rf.close()
key, value = new_value.split('=')
keys = key.split('.')
inner_dict = yaml_doc
for i in keys[:-1]:
inner_dict = inner_dict[i]
inner_dict[keys[-1]] = value
with open(file, 'w') as wf:
if strip_qoutes:
wf.write(yaml.dump(yaml_doc,
default_flow_style=False).replace("'", "").replace('"', ""))
else:
wf.write(yaml.dump(yaml_doc, default_flow_style=False))
wf.close()
I wanna make a dictionary has name's key & data.In views.py I wrote
data_dict ={}
def try_to_int(arg):
try:
return int(arg)
except:
return arg
def main():
book4 = xlrd.open_workbook('./data/excel1.xlsx')
sheet4 = book4.sheet_by_index(0)
data_dict_origin = OrderedDict()
tag_list = sheet4.row_values(0)[1:]
for row_index in range(1, sheet4.nrows):
row = sheet4.row_values(row_index)[1:]
row = list(map(try_to_int, row))
data_dict_origin[row_index] = dict(zip(tag_list, row))
if data_dict_origin['name'] in data_dict:
data_dict[data_dict_origin['name']].update(data_dict_origin)
else:
data_dict[data_dict_origin['name']] = data_dict_origin
main()
When I printed out data_dict,it is
OrderedDict([(1, {'user_id': '100', 'group': 'A', 'name': 'Tom', 'dormitory': 'C'}), (2, {'user_id': '50', 'group': 'B', 'name': 'Blear', 'dormitory': 'E'})])
My ideal dictionary is
dicts = {
Tom: {
'user_id': '100',
'group': 'A',
'name': 'Tom',
'dormitory': 'C'
},
Blear: {
},
}
How should I fix this?What should I write it?
The code is using the wrong key in the dictionary. The keys are 1, 2, and do not have the name key. You can use this code instead:
for value in data_dict.values():
if value['name'] in data_dict:
data_dict[value['name']].update(value)
else:
data_dict[value['name']] = value
Your data_dict_origin has numbers as keys and dicts as values (which technically makes it a sparse array of dicts). The "name" key exists in those dicts, not in your data_dict.