The Objective
I need to take an array with data that can be displayed in 2 dimensions, and paste it over any part of a 2D array as if it were an image. This function would be similar to the Python library Pillow’s paste function.
Example
Say I have a 2D array with a size of 5×5, with a default value of 0.
[ [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0] ]
And I have an average array with the length of 4, which can be assembled into 2×2 form.
[0, 1, 1, 1]
With this, I need a function to, as if these arrays were images, ‘paste’ the second over the first. With a position (anchored from the top left) of (1,2), it would result in this 2D array.
[ [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 1, 1, 0, 0], [0, 0, 0, 0, 0] ]
My Attempt
Here is my attempt at creating the Python code.
class Indexed:
    def __init__(self, x, y):
        self.array = [[0]*x]*y
        self.dimensions = (x, y)
    def writeImage(self, indexed, x, y, width, height):
        index = 0
        for ArrayY in range(height):
            self.array[ArrayY] = [0]*self.dimensions[0]
            for ArrayX in range(width):
                self.array[1 + ArrayY][x + ArrayX] = indexed[index]
                index+=1
                
Test = Indexed(12,12)
Test.writeImage(
        [
            0,0,7,0,0,7,0,0,
            0,0,7,0,0,7,0,0,
            0,0,7,0,0,7,0,0,
            7,0,0,0,0,0,0,7,
            7,7,7,7,7,7,7,7
        ],
        0,0, 8,5
    )
print(Test.array)
The Problem
If you attempt to run the code above, you will see that it outputs this result.
[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0] ]
This is the intended result.
[ [0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 0, 0], [0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 0, 0], [0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 0, 0], [7, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0], [7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]
I’ve tinkered with it a lot and haven’t found any answers online for why these arrays work the way they do here.
Any help is greatly appreciated.
Advertisement
Answer
When you initialise self.array [[0]*x]*y. The [0]*x is only shallow copied (reference only) y times, which means all of the row is basically the same array.
Since it is the same array, it’s final value would be the last row, i.e. 7,7,7,7,7,7,7,7. Thats why the one updated is such value.
Also noted the index is incorrect in the writeImage
from pprint import pprint
class Indexed:
    def __init__(self, x, y):
        self.array = [0]*y
        for i in range(y):
            self.array[i] = [0]*x
        self.dimensions = (x, y)
    def writeImage(self, indexed, x, y, width, height):
        for ArrayY in range(height):
            for ArrayX in range(width):
                index = (ArrayY * width) + ArrayX
                self.array[y + ArrayY][x + ArrayX] = indexed[index]
                
Test = Indexed(12,12)
Test.writeImage(
        [
            0,0,7,0,0,7,0,0,
            0,0,7,0,0,7,0,0,
            0,0,7,0,0,7,0,0,
            7,0,0,0,0,0,0,7,
            7,7,7,7,7,7,7,7
        ],
        0,0, 8,5
    )
pprint(Test.array)
