Bentley4
Bentley4

Reputation: 11028

Alter values of dictionaries which have the same keys in a list

I had this:

[{'name': 'Peter'}, {'name': 'Anna'}]

And I wanted to make this out of it:

[{'name': 'Peter Williams'}, {'name': 'Anna Williams'}]

So I did:

>>> li = [{'name': 'Peter'}, {'name': 'Anna'}]
>>> new_li = []
>>> dic = {}
>>> for i in li:
...     dic["name"] = i["name"] + " Williams"
...     new_li.append(dic)

But:

>>> new_li
[{'name': 'Anna Williams'}, {'name': 'Anna Williams'}]

Why?

Could you also show how to best get [{'name': 'Peter Williams'}, {'name': 'Anna Williams'}]?

Edit

The reason why I didn't understand this behavior is because I assumed that:

>>> dict = {'name':'Peter'}
>>> lis = [dict]
>>> dict['name'] = 'Olaf'

Where

>>> print lis

gives

[{'name': 'Peter'}]

While it actually is

[{'name': 'Olaf'}]

Upvotes: 1

Views: 71

Answers (4)

Acorn
Acorn

Reputation: 50497

Because you're using the same dictionary object in each iteration.

On the second iteration, you are altering the value that you assigned to the name key in the previous iteration, and your list ends up containing two references to the same object.

I'd strongly recommend checking out the "Python Tutor" tool (pythontutor.com), which allows you to visualise the execution of some python code, and see what objects are being created in the stack. e.g. Python Tutor with your code

The correct way to do what you wanted would be:

li = [{'name': 'Peter'}, {'name': 'Anna'}]
new_li = []
for p in li:
    new_p = {'name': p['name'] + ' Williams'}
    new_li.append(new_p)

This way a new dictionary object is created with each iteration.

A more concise solution:

li = [{'name': 'Peter'}, {'name': 'Anna'}]
new_li = [{'name': p['name'] + ' Williams'} for p in li]

Upvotes: 2

pydsigner
pydsigner

Reputation: 2885

You have run into a really nasty problem. The problem is with your dic. You are iterating over the list of names, and first you hit the one with 'Peter'. At this point, you set dic to {'name': 'Peter Williams'} and append it. But then, you hit the one with 'Anna' and change that very same dic to {'name': 'Anna Williams'}. So you end up with the same dictionary in your list twice. To fix this, you will need to do this instead:

new_li = []
for i in li:
      n_li.append({'name': i['name'] + ' Williams'})

Upvotes: 0

Keith
Keith

Reputation: 43024

I'm assuming you want to alter it in-place. You don't need to make a new dict.

for d in inlist:
    d["name"] += " Williams"

Is all you have to do.

Upvotes: 0

Andrew Clark
Andrew Clark

Reputation: 208475

You need to create a new dictionary on each iteration of the loop, otherwise on each iteration you modify and append the same object to new_li:

>>> li = [{'name': 'Peter'}, {'name': 'Anna'}]
>>> new_li = []
>>> for i in li:
...     new_li.append({'name': i['name'] + ' Williams'})
...
>>> new_li
[{'name': 'Peter Williams'}, {'name': 'Anna Williams'}]

Upvotes: 0

Related Questions