Anon
Anon

Reputation: 113

Python dictionary updating old entries when appending to an array

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!

Upvotes: 1

Views: 61

Answers (1)

atline
atline

Reputation: 31584

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.

Upvotes: 1

Related Questions