18

I have a list of lists, each list within the list contains 5 items, how do I change the values of the items in the list? I have tried the following:

    for [itemnumber, ctype, x, y, delay] in execlist:
        if itemnumber == mynumber:
            ctype = myctype
            x = myx
            y = myy
            delay = mydelay

Originally I had a list of tuples but I realized I cant change values in a tuple so I switched to lists but I still cant change any of the values. If I print ctype, x, y, delay, myctype, myx, myy, or mydelay from within the for loop it appears that everything is working but if I print execlist afterwards I see that nothing has changed.

Wichid Nixin
  • 287
  • 1
  • 4
  • 14
  • Are `itemnumber`s unique? Or is there another reason why you want to iterate through the entire list, even after a replacement has been done? – Tim Pietzcker Dec 06 '12 at 21:06

8 Answers8

17

The problem is that you are creating a copy of the list and then modifying the copy. What you want to do is modify the original list. Try this instead:

for i in range(len(execlist)):
    if execlist[i][0] == mynumber:
         execlist[i][1] = myctype
         execlist[i][2] = myx
         execlist[i][3] = myy
         execlist[i][4] = mydelay
tweetotaler
  • 83
  • 1
  • 7
4

You could use enumerate():

for index, sublist in enumerate(execlist):
   if sublist[0] == mynumber:
       execlist[index][1] = myctype
       execlist[index][2] = myx
       execlist[index][3] = myy
       execlist[index][4] = mydelay
       # break

You can remove the # if execlist only contains at most one sublist whose first item can equal mynumber; otherwise, you'll cycle uselessly through the entire rest of the list.

And if the itemnumbers are in fact unique, you might be better off with a dictionary or at least an OrderedDict, depending on what else you intend to do with your data.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
3

You need to assign via indexes. Let's say you've got a list of lists, where the inner lists each have 5 items like you describe. If you want to iterate through them and change the value of the second item in each inner list, you could do something like:

l = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]
for i in l:
    i[1] = "spam"

print l
(output) [[0, "spam", 2, 3, 4], [5, "spam", 7, 8, 9], [10, "spam", 12, 13, 14]]
BenTrofatter
  • 2,148
  • 1
  • 13
  • 13
1

Variable unpacking does not seem to pass the reference but copies the values. An solution would be to do it like this:

foo = [[1, "gggg"], [3, "zzzz"]]

for item in foo:
    item[0] = 2
    item[1] = "ffff"

print(foo)

>>>> [[2, 'ffff'], [2, 'ffff']] 
RickyA
  • 15,465
  • 5
  • 71
  • 95
0

Don't assign local variables in lists. In the loop

for i in lis:
    i = 5

Just sets the variable i to 5 and leaves the actual contents of the list unchanged. Instead, you have to assign it directly:

for i in range(len(lis)):
     lis[i] = 5

The same applied for lists of lists, although in this case the local variable doesn't have to be assigned so you can use the for...in construct.

for i in listoflists:
     for i2 in range(len(i)):
          i[i2] = 5 #sets all items in all lists to 5
ApproachingDarknessFish
  • 14,133
  • 7
  • 40
  • 79
0

Changing the variables assigned in the for does not change the list. Here's a fairly readable way to do what you want:

execlist = [
    #itemnumber, ctype, x, y, delay
    [1, 2, 3, 4, 5],
    [6, 7, 8, 9, 10],
    [11, 12, 13, 14, 15],
]

mynumber, myctype, myx, myy, mydelay = 6, 100, 101, 102, 104

for i, sublist in enumerate(execlist):
   if sublist[0] == mynumber:
        execlist[i] = [mynumber, myctype, myx, myy, mydelay]

print execlist

Output:

[[1, 2, 3, 4, 5], [6, 100, 101, 102, 104], [11, 12, 13, 14, 15]]
martineau
  • 119,623
  • 25
  • 170
  • 301
0

The iterator variables are copies of the original (Python does not have a concept of a reference as such, although structures such as lists are referred to by reference). You need to do something like:

for item in execlist:
    if item[0] == mynumber:
        item[1] = ctype
        item[2] = myx
        item[3] = myy
        item[4] = mydelay

item itself is a copy too, but it is a copy of a reference to the original nested list, so when you refer to its elements the original list is updated.

This isn't as convenient since you don't have the names; perhaps a dictionary or class would be a more convenient structure.

dbrobins
  • 499
  • 1
  • 3
  • 9
0

Here is an example I used recently, it was a real mind bender but hopefully it can help out some one!

pivot_peaks is a list of pandas data frames some of them are duplicates.

# Create a new list with only a single entry for each item
new_list = []

for obj_index, obj in enumerate(pivot_peaks):
    add_new_frame = False

    if len(new_list) == 0:
        new_list.append(obj)
    else:
        for item in new_list:
            if item.equals(obj):
                add_new_frame = False
                break
            else:
                add_new_frame = True

        if add_new_frame == True:
            new_list.append(obj)
Erik Ware
  • 31
  • 5