Python dictionary updating old entries when appending to an array

Question:

I have been looking at this too long. I am writing code to use known algorithms to increase the size of an ArrayList as I am adding to it. Every time the size of the ArrayList changes I add the new size to an array which is then added to a dictionary.

Here is the code for the ArrayList class I am using

class ArrayList:
def __init__(self, growfn):
    '''Initializes the empty ArrayList with the specified growth function.'''
    self.size = 0
    self.used = 0
    self.array = []
    self.grow = growfn

def get(self, index):
    if index < self.size:
        return self.array[index]
    # exception handling
    return None

def add(self, value):
    if self.used == self.size:
        newSize = self.grow(self.size)
        if newSize <= self.size:
            # exception handling
            return
        newArray = self.array[:]+[None for i in range(self.size,newSize)]
        self.array = newArray
        self.size = newSize
    self.array[self.used] = value
    self.used = self.used + 1
    return None

Here is the code I have written to test this. This function takes 3 parameters: A list containing the max sizes of the array, the function for the algorithm I am using to increase the size of the ArrayList, and the number of tries that it will run for.

def analyzePerformance(nList, gfn, tries):
data = []
sizes_array = []
averages = []
arr = ArrayList(gfn)
for num in nList:
    for j in range(tries):
        current_size = 0
        start = time()
        while arr.size < num:
            arr.add(None)
            if arr.size != current_size:
                sizes_array.append(arr.size)
                current_size = arr.size
        end = time()
        averages.append(end - start)
    data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array})) 
return data

And finally the code where I call to the function

def main():
for result in analyzePerformance([1,10,100], double, 11):
    print(result)

double is a function that simply doubles the size of the array

Here is my current output:

{'grow': <function double at 0x7f3274eb4f28>, 'N': 1, 'seconds': 3.034418279474432e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 10, 'seconds': 4.659999500621449e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 100, 'seconds': 7.369301535866477e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}

And here is what I need the output to be

{'grow': <function double at 0x7f3274eb4f28>, 'N': 1, 'seconds': 3.034418279474432e-07, 'sizes': [1]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 10, 'seconds': 4.659999500621449e-07, 'sizes': [1, 2, 4, 8, 16]}
{'grow': <function double at 0x7f3274eb4f28>, 'N': 100, 'seconds': 7.369301535866477e-07, 'sizes': [1, 2, 4, 8, 16, 32, 64, 128]}

Why is it that when I add new elements to the dictionary with different lengths of sizes arrays it updates the old dictionaries to have the longer arrays as well? Any help is appreciated, thanks!

Asked By: Anon

||

Answers:

You may want to have a look for Shallow and deep copy operations:

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

For your next code, the sizes_array will be reused among different iterations, although it has been added into data list:

data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array}))

To fix this, you need to change above to next:

data.append(dict({'grow': gfn, 'N': num, 'seconds': mean(averages), 'sizes': sizes_array.copy()}))

With above, you will see a copied object for sizes_array which meet your requirement.

Answered By: atline
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.