0

I guess, list is an object, so this behavior must be due to its reference being appended, and so all the elements get updated! How does this work exactly and what's the right way to do this?

Code (to increment index position discovered):

# generating labels for debugging
#labels = [3]*3 + [1]*3  + [4]*2
labels = [3, 3, 3, 1, 1, 1, 4, 4]
print "labels list is", labels

counter_table = []
#counter = [0]*6
counter = [0 for i in range(6)]
for i in labels:
    curr_label = i
    counter[curr_label] = counter[curr_label] + 1
    print "current counter list is", counter
    counter_table.append(counter)
print "final counter_table is", counter_table

Output:

labels list is [3, 3, 3, 1, 1, 1, 4, 4]
current counter list is [0, 0, 0, 1, 0, 0]
current counter list is [0, 0, 0, 2, 0, 0]
current counter list is [0, 0, 0, 3, 0, 0]
current counter list is [0, 1, 0, 3, 0, 0]
current counter list is [0, 2, 0, 3, 0, 0]
current counter list is [0, 3, 0, 3, 0, 0]
current counter list is [0, 3, 0, 3, 1, 0]
current counter list is [0, 3, 0, 3, 2, 0]
final counter_table is [[0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0], [0, 3, 0, 3, 2, 0]]
devautor
  • 2,506
  • 4
  • 21
  • 31
  • just re-initialise `counter` in the loop. Unless you want to stack the changes and get every "frame" in which case, a copy has to be created. – Ma0 Jan 18 '17 at 10:28
  • that's exactly what is happening, you are appending the same list reference every time, see http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list for possible solutions to this problem – jarandaf Jan 18 '17 at 10:30
  • You may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Jan 18 '17 at 10:38
  • @jarandaf That's elaborated, thanks! – devautor Jan 18 '17 at 11:23

2 Answers2

2

you're reusing the reference of counter, which is probably what you want to keep memory of what's happening.

So just store a copy of your list

counter = [0]*6
for curr_label in labels:
    counter[curr_label] += 1
    print "current counter list is", counter
    counter_table.append(counter[:]) # create a copy

Aside: I saw that you were reluctant to use counter = [0]*6: it's perfectly all right to use * on list of immutable objects (no risk of using the same reference in that case)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0

You need to generate a copy of the list:

counter_table.append(list(counter))

otherwise a modification to counter will alter all occurrences in counter_table.

alexblae
  • 746
  • 1
  • 5
  • 13