user1550725
user1550725

Reputation: 177

change item in the list with a dictionary

dic = {'a':'1','b':'2'}
lis = ['a','b']
for c in lis:
    c = dic[c]
print lis

The list was not changed. I had expected that the list would be changed to ['1','2']. Can anyone explain?

Upvotes: 3

Views: 119

Answers (4)

pradyunsg
pradyunsg

Reputation: 19406

Try using indexes instead of a variable...

for i in range(len(li)):
    c = li[i]
    li[i] = dic[c]
print li

Also, never use list as a variable name..
or use enumerate like

for i, c in enumerate(li):
    li[i] = dic[c]
print li

or list comprehensions

lis = [dic[c] if c in dic else c for c in lis]

Why not what you are doing?
When you use for x in y:, x gets the value of an object/item in y
So, if you change the value of x, you don't change the value of y[i], i being the index that you are on.

So, if you do this

>>> y = range(5,10)
>>> for x in y:
    i = y.index(x)
    x += 10
    print i
    print 'Value of x    : %3d, id: %7d' % (x, id(x))
    print 'Value of y[i] : %3d, id: %7d' % (y[i], id(y[i]))
    print '-'*31

You'll see the difference

Upvotes: 2

Joel Cornett
Joel Cornett

Reputation: 24788

When you do

for c in myList:
    c = something

You are rebinding the name c to whatever "something" is, in this case the value at dic[c]. In order to get Python to actually "reach into" the list, you have to call a method on that list--the method list.__setitem__() tells Python to access the actual list object and mutate an item in that list, not to do a simple variable assignment.

for i, c in enumerate(myList):
    myList.__setitem__(dic[c])

This, of course, can also be written as (the more pythonic):

for i, c in enumerate(myList):
    myList[i] = dic[c]

It looks like a variable assignment, but it's not.

Upvotes: 2

Abhijit
Abhijit

Reputation: 63707

The most important thing you are missing in your iteration is the fact that assigning the element to the name c, c=dic[c] re-binds c to a new object and does not update the original object in place. Consider the following Demonstration

>>> for i, c in enumerate(lst):
    print id(c), id(lst[i]),
    c=dic[c]
    print id(c)


4935168 4935168 4934712
4935192 4935192 5496728

So though before the assignment both the list element and c refers the same object within the list but assigning the value of the dictionary just changes the references

Note, here id just refers to the identifier of the object of reference

Note, as you are changing the entire list, its easier and faster to use List Comprehension

lst = [dic[e] for e in lst]
['1', '2']

Warning Don;t name a variable to a built-in

Upvotes: 3

Tim Pietzcker
Tim Pietzcker

Reputation: 336108

No, that's not how list iteration works. c is a new object at each iteration, and if you change that object, the original list is (thankfully!) not modified.

If you do want that, use enumerate():

dic = {'a':'1','b':'2'}
lis = ['a','b']
for i, c in enumerate(lis):
    lis[i] = dic[c]
print lis

Upvotes: 4

Related Questions