Create a list of dictionaries without overwriting [duplicate] - python

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 3 years ago.
I am looking for a way to update list listOfuser with dict User without over writing any last index.
[{'name': 'john', 'fimily': 'johny', 'studentId': '2120', 'age': 23},
{'name': 'mick', 'fimily': 'micky', 'studentId': '2121', 'age': 24}]
Result which I currently have:
[{'name': 'mick', 'fimily': 'micky', 'studentId': '2121', 'age': 24},
{'name': 'mick', 'fimily': 'micky', 'studentId': '2121', 'age': 24}]
Code snippet used to produce the said result:
UserInfo = {}
listOfUser = []
UserInfo['name'] = "john"
UserInfo['fimily'] = 'johny'
UserInfo['studentId'] = '2120'
UserInfo['age'] = 23
listOfUser.append(UserInfo)
print(listOfUser)
UserInfo['name'] = "mick"
UserInfo['fimily'] = 'micky'
UserInfo['studentId'] = '2121'
UserInfo['age'] = 24
listOfUser.append(UserInfo)
print(listOfUser)
is there any way ?

You need to append a copy of the dictionary to the list
listOfUser.append(UserInfo.copy())
output
[{'name': 'john', 'fimily': 'johny', 'studentId': '2120', 'age': 23},
{'name': 'mick', 'fimily': 'micky', 'studentId': '2121', 'age': 24}]

Related

Python: update a nested dictionary [duplicate]

This question already has answers here:
How do I merge two dictionaries in a single expression in Python?
(43 answers)
Update value of a nested dictionary of varying depth
(28 answers)
Closed 6 months ago.
This post was edited and submitted for review 6 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Let's say I am given a nested dicionary my_dict and another nested dict update: a sequence of keys (valid in my_dict) with a value to be assigned to the leaf at this sequence. For example,
my_dict = {
'city': 'NYC',
'person1': {'age': 25, 'name': 'Anna'},
'person2': {'age': 30, 'name': 'Bob'}
}
update0 = {'city': 'London'}
update1 = {'person1': {'age': 24}}
update2 = {'person2': {'age': 31}}
I need a function UpdateDict such that UpdateDict(my_dict, update1) will return
{
'city': 'NYC',
'person1': {'age': 24, 'name': 'Anna'},
'person2': {'age': 30, 'name': 'Bob'}
}
and UpdateDict(my_dict, update0) will return
{
'city': 'London',
'person1': {'age': 25, 'name': 'Anna'},
'person2': {'age': 30, 'name': 'Bob'}
}
In c++ I would have used explicit pointers/references to subdicts, but in python I'm not sure what to do, given that I don't know in advance the depth of the second argument (update one).
EDIT: if I try {**my_dict, **update1} or my_dict.update(update1) I get
{
'city': 'NYC',
'person1': {'age': 24},
'person2': {'age': 30, 'name': 'Bob'}
}
which is not desired: it does not change the value at a particular leaf only, but instead removes all the keys at the same level.
EDIT2: if someone needs this, I've solved it as follows
def UpdateDict(original, param):
for key in param.keys():
if type(param[key]) == dict:
UpdateDict(original[key], param[key])
else:
original[key] = param[key]

Create a List of Dictionaries using Comprehension

I currently have a list of strings that I am trying to create each string item into a dictionary object and store it within a list.
In attempting to create this list of dictionaries, I repeatedly create one big dictionary instead of iterating through item by item.
My code:
clothes_dict = [{clothes_list[i]: clothes_list[i + 1] for i in range(0, len(clothes_list), 2)}]
The error (All items being merged into one dictionary):
clothes_dict = {list: 1} [{'name': 'Tom', 'age': 10}, {'name': 'Mark', 'age': 5}, {'name': 'Pam', 'age': 7}]
0 = {dict: 2} {'name': 'Tom', 'age': 10}, {dict: 2} {'name': 'Mark', 'age': 5}, {'name': 'Pam', 'age': 7}```
Target Output (All Items being created into separate dictionaries within the single list):
clothes_dict = {list: 3} [{'name': 'Tom', 'age': 10}, {'name': 'Mark', 'age': 5}, {'name': 'Pam', 'age': 7}]
0 = {dict: 2} {'name': 'Tom', 'age': 10}
1 = {dict: 2} {'name': 'Mark', 'age': 5}
2 = {dict: 2} {'name': 'Pam', 'age': 7}```
I am attempting to make each entry within the list a new dictionary in the same form as the target output image.
clothes_dict = [{clothes_list[i]: clothes_list[i + 1]} for i in range(0, len(clothes_list), 2)]
You misplaced your closing right curly brace '}' in your list comprehension and placed it at the end which meant you was performing a dictionary comprehension as opposed to a list comprehension with each item being a dictionary.
Your code creates a list with a single dictionary:
clothes_dict = [{clothes_list[i]: clothes_list[i + 1] for i in range(0,l en(clothes_list), 2)}]
If you (for some reason) want a list of dictionaries with single entries:
clothes_dict = [{clothes_list[i]: clothes_list[i + 1]} for i in range(0,l en(clothes_list), 2)]
However, it seems to me that this may be a bit of an XY problem - in what case is a list of single-entry dictionaries the required format? Why not use a list of tuples for example?

What is the most efficient way to create nested dictionaries in Python?

I currently have over 10k elements in my dictionary looks like:
cars = [{'model': 'Ford', 'year': 2010},
{'model': 'BMW', 'year': 2019},
...]
And I have a second dictionary:
car_owners = [{'model': 'BMW', 'name': 'Sam', 'age': 34},
{'model': 'BMW', 'name': 'Taylor', 'age': 34},
.....]
However, I want to join together the 2 together to be something like:
combined = [{'model': 'BMW',
'year': 2019,
'owners: [{'name': 'Sam', 'age': 34}, ...]
}]
What is the best way to combine them? For the moment I am using a For loop but I feel like there are more efficient ways of dealing with this.
** This is just a fake example of data, the one I have is a lot more complex but this helps give the idea of what I want to achieve
Iterate over the first list, creating a dict with the key-val as model-val, then in the second dict, look for the same key (model) and update the first dict, if it is found:
cars = [{'model': 'Ford', 'year': 2010}, {'model': 'BMW', 'year': 2019}]
car_owners = [{'model': 'BMW', 'name': 'Sam', 'age': 34}, {'model': 'Ford', 'name': 'Taylor', 'age': 34}]
dd = {x['model']:x for x in cars}
for item in car_owners:
key = item['model']
if key in dd:
del item['model']
dd[key].update({'car_owners': item})
else:
dd[key] = item
print(list(dd.values()))
OUTPUT:
[{'model': 'BMW', 'year': 2019, 'car_owners': {'name': 'Sam', 'age': 34}}, {'model': 'Ford', 'year': 2010, 'car_owners': {'name': 'Taylor',
'age': 34}}]
Really, what you want performance wise is to have dictionaries with the model as the key. That way, you have O(1) lookup and can quickly get the requested element (instead of looping each time in order to find the car with model x).
If you're starting off with lists, I'd first create dictionaries, and then everything is O(1) from there on out.
models_to_cars = {car['model']: car for car in cars}
models_to_owners = {}
for car_owner in car_owners:
models_to_owners.setdefault(car_owner['model'], []).append(car_owner)
combined = [{
**car,
'owners': models_to_owners.get(model, [])
} for model, car in models_to_cars.items()]
Then you'd have
combined = [{'model': 'BMW',
'year': 2019,
'owners': [{'name': 'Sam', 'age': 34}, ...]
}]
as you wanted

Find a value in a list of dicts [duplicate]

This question already has answers here:
Get the first item from an iterable that matches a condition
(18 answers)
Closed 4 years ago.
Let:
M = [{'name': 'john', 'result': 12},
{'name': 'sara', 'result': 20},
{'name': 'karl', 'result': 11}]
If I want to find Sara's result, I thought about:
M[[m['name'] for m in M].index('sara')]['result'] # hard to read, but works
and
[m['result'] for m in M if m['name'] == 'sara'][0] # better
Is there an even more natural way to do this in Python?
Use a generator with next().
next(m['result'] for m in L if m['name'] == 'sara')
If you have several lookups to perform, linear search isn't the best option.
Rebuild a dictionary once with the proper key (name):
M = [{'name': 'john', 'result': 12},
{'name': 'sara', 'result': 20},
{'name': 'karl', 'result': 11}]
newdict = {d["name"] : d["result"] for d in M}
It creates:
{'john': 12, 'karl': 11, 'sara': 20}
now when you need the result from a name, just do:
print(newdict.get('sara'))

Obtain a set of unique values from a dictionary of lists

I have a list of dictionaries in which the dictionaries also contain a list.
I want to generate a set of the values of the respective nested lists so that I end up with a set of all of the unique items (in this case, hobbies).
I feel a set is perfect for this since it will automatically drop any duplicates, leaving me with a set of all of the unique hobbies.
people = [{'name': 'John', 'age': 47, 'hobbies': ['Python', 'cooking', 'reading']},
{'name': 'Mary', 'age': 16, 'hobbies': ['horses', 'cooking', 'art']},
{'name': 'Bob', 'age': 14, 'hobbies': ['Python', 'piano', 'cooking']},
{'name': 'Sally', 'age': 11, 'hobbies': ['biking', 'cooking']},
{'name': 'Mark', 'age': 54, 'hobbies': ['hiking', 'camping', 'Python', 'chess']},
{'name': 'Alisa', 'age': 52, 'hobbies': ['camping', 'reading']},
{'name': 'Megan', 'age': 21, 'hobbies': ['lizards', 'reading']},
{'name': 'Amanda', 'age': 19, 'hobbies': ['turtles']},
]
unique_hobbies = (item for item in people['hobbies'] for hobby in people['hobbies'].items())
print(unique_hobbies)
This generates an error:
TypeError: list indices must be integers or slices, not str
My comprehension is wrong, but I am not sure where. I want to iterate through each dictionary, then iterate through each nested list and update the items into the set, which will drop all duplicates, leaving me with a set of all of the unique hobbies.
You could also use a set-comprehension:
>>> unique_hobbies = {hobby for persondct in people for hobby in persondct['hobbies']}
>>> unique_hobbies
{'horses', 'lizards', 'cooking', 'art', 'biking', 'camping', 'reading', 'piano', 'hiking', 'turtles', 'Python', 'chess'}
The problem with your comprehension is that you want to access people['hobbies'] but people is a list and can only index lists with integers or slices. To make it work you need to iterate over you list and then access the 'hobbies' of each of the subdicts (like I did inside the set-comprehension above).
I got it:
unique_hobbies = set()
for d in people:
unique_hobbies.update(d['hobbies'])
print(unique_hobbies)

Categories