0

I have a dictionary with arrays (same length) associated to strings. My goal is to create a new dictionary with the same keys but cutting the arrays, keeping only the elements I need. I wrote a function to do it but the problem is that it returns a dictionary with the same array (correct cut length) associated to every key, while the print command i put to control show the correct association. Here's the function:

def extract_years(dic,initial_year,final_year):

    dic_extr = {}
    l = numpy.size(dic[dic.keys()[0]])

    if final_year != 2013 : 
        a = numpy.zeros((final_year - initial_year)*251)
    elif final_year == 2013 :
        a = numpy.zeros(l - (initial_year-1998)*251)

    for i in range(0,len(dic)):
        #print i
        for k in range (0,numpy.size(a)):
            a[k] = dic[dic.keys()[i]][(initial_year-1998)*251 + k]          
            #print k

        dic_extr[dic.keys()[i]] = a
        print dic.keys()[i]
        print dic_extr[dic.keys()[i]]


    print dic_extr.keys()
    print dic_extr
    return dic_extr

as I said, print dic_extr[dic.keys()[i]] shows the correct results while the final print dic_extr shows a dictionary with the same array associated to every key.

3
  • Please fix indentation. Commented Aug 30, 2017 at 10:14
  • Could you give an example of the function call which have an unexpected result, and with the result that you would expect? Commented Aug 30, 2017 at 10:33
  • pastebin.com/GSncW5DE i pasted the terminal output here as the dictionary has more than 300 elements and the arrays very long. As you can see the first prints are the print dic.keys()[i] print dic_extr[dic.keys()[i]] while the last is print dic_extr which is completely different, i just expected the whole first print all together in the new dictionary Commented Aug 30, 2017 at 10:39

2 Answers 2

1

In Python, every object is a pointer. So, you should have to create a new instance of a for each iteration of the outer for loop. You could do this, for example, initializing the a array inside of that loop, like this:

def extract_years(dic,initial_year,final_year):

    dic_extr = {}
    l = numpy.size(dic[dic.keys()[0]])

    for i in range(0,len(dic)):

        if final_year != 2013 : 
            a = numpy.zeros((final_year - initial_year)*251)
        elif final_year == 2013 :
            a = numpy.zeros(l - (initial_year-1998)*251)

        for k in range (0,numpy.size(a)):
            a[k] = dic[dic.keys()[i]][(initial_year-1998)*251 + k]          
            #print k

        dic_extr[dic.keys()[i]] = a
        print dic.keys()[i]
        print dic_extr[dic.keys()[i]]


    print dic_extr.keys()
    print dic_extr
    return dic_extr

Perhaps this is not the most elegant solution, but I think that it should work.

Sign up to request clarification or add additional context in comments.

Comments

0

I think you ran into the typical problem of mutability and pythons way to define variables:

  1. You define a to be mutable type by using numpy.zeros().
  2. Then you make a have a certain values in it, but you actually have a pointer to a list of pointers, pointing to the actuall values.
  3. By using dic_extr[dic.keys()[i]] = ayou copy this pointer into the dic_extr array, not the list of pointers.
  4. Then you change the objects that the pointer list refers to.
  5. By using dic_extr[dic.keys()[i]] = ayou copy the pointer to the list of pointers into the dic_extr array, again not the pointer list itself.

In the end both pointer point to the same pointer list. Easy example:

a = [1, 2, 3, 4, 5]
b = a
b[0] = 10
print(a) # returns [10, 2, 3, 4, 5]

You can use dic_extr[dic.keys()[i]] = a[:] to actually make a copy of a.

Here is also a nice explaination to mutability in python.

2 Comments

Does it still refer to the same thing or what is the problem?
just same output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.