Changes in for-loop don't apply outside loop

value = # A custom array I've made with dictionaries in them. Pretend original price values were [1.0, 5.0, 7.0, 9.0, 12.0]. 

for cur_perm in perm_array

  println(cur_perm) # looks something like [2.0, 10.0, 20.0, 30.0, 40.0] for this iteration lets pretend

  dupl_of_value = copy(value) 

  for jj in eachindex(cur_perm) 
    
    dupl_of_value[jj]["price"] = cur_perm[jj] 
    println(dupl_of_value[jj]["price"]) # prints out the new value, e.g. 2.0 when jj=1, which is correct and what I want it to do

  end 

  println(dupl_of_value[1]["price"]) # prints out the original value of 1.0, which is incorrect and not what I want it to do 

end 

Hi all,

Above is a snippet from my program/script. In general, the program generates permutations and is supposed to apply them all as new entries in a dictionary. My program is generating every permutation from the data it is given correctly, however, it is not applying them all. The above snippet looks to be roughly where it goes wrong for me.

Inside the second FOR loop, I overwrite the “price” key at index jj of dupl_of_value with the matching jj value from cur_perm, and this works fine in the print statement immediately after. However, when the second FOR loop ends, none of these changes seem to persist, as the “price” key at index 1 of dupl_of_value is not the correct value when I print it.

Would anybody have any suggestions as to why this might be the case please? I imagine it’s probably some simple mistake I’m making with scope, but I’m yet to spot it and it’s left me stumped for a bit. Alternatively, maybe I’m missing some idiosyncrasy with Julia?

Thanks for any help.

Works as expected.

julia> value = [Dict("price"=>x) for x in [1.0, 5.0, 7.0, 9.0, 12.0]]
       perm_array = [[2.0, 10.0, 20.0, 30.0, 40.0]]
       for cur_perm in perm_array
           println(cur_perm)
           dupl_of_value = copy(value)
           for jj in eachindex(cur_perm)
               dupl_of_value[jj]["price"] = cur_perm[jj]
               println(dupl_of_value[jj]["price"])
           end
           println(dupl_of_value[1]["price"])
       end
[2.0, 10.0, 20.0, 30.0, 40.0]
2.0
10.0
20.0
30.0
40.0
2.0

Are you sure you’re not mistaking something else?

For example: copy creates a copy of the value container, but it doesn’t copy the data inside it—all the entries point to exactly the same dictionaries; all(splat(≡), zip(value, dupl_of_value)) is true. If you want the contents to be copied recursively, you need to use deepcopy instead.


println(value) # I can include a snippet of the structure of value if necessary
# In the original `value` variable, all of the values for ["price"]["price"] are 200.0

for good_perm in filtered_valid_perm_array
    
  println(good_perm)
  
  dupl_of_value = deepcopy(value)
    
  for jj in 1:(length(good_perm))
    dupl_of_value[jj]["price"]["price"] = good_perm[jj]
    
    if jj == 1
      println(string("good: ", dupl_of_value[jj]["price"]["price"]))
    end

  end
    
  println(string("1 bad: ", dupl_of_value[1]["price"]["price"]))
  println(string("2 bad: ", dupl_of_value[2]["price"]["price"]))
  # printing indexes 3, 4 and 5 seem to be fine, although I may have noticed 
  # that printing index 2 can show it as incorrect on some iterations,  
  # though I may be misremembering. 

  # More code after this 

image

Hi there,

Thanks for your reply. I previously was using deepcopy instead of copy but I was still running into the same issue. I’ve re-done my snippet using deepcopy and made some other small changes/expansions too. Probably the main difference is that the “price” key is nested twice in the dupl_of_value dictionary; I left it at one nesting in the first snippet for simplicity and because I didn’t think it’d have any impact but maybe I’m wrong?

I’ve also included a snippet of the output I’m receiving when I run my script. The intention is to have “1 bad” match “good”. I’ve noticed that when “1 bad” does not match “good”, the value for “1 bad” is instead the value of the 5th index in the good_perm array. Based on this, whenever the values of the 1st index and 5th index of good_perm are the same, then “1 bad” and “good” do match (as we’d expect, though I suspect this is coincidence and doesn’t explain why good_perm index 5 is assigned at dupl_of_value index 1).

Would anybody have any guess as to why the value of dupl_of_value[1][“price”][“price”] is taking on the value of good_perm[5] when outside of the inner FOR loop, but not when inside of the inner FOR loop?

Hope this all makes sense, thanks all.

Works as expected.

julia> value = [Dict("price"=>Dict("price"=>x)) for x in [200.0, 200.0, 200.0, 200.0, 200.0]]
       filtered_valid_perm_array = [[2.0, 10.0, 20.0, 30.0, 40.0]]
       for good_perm in filtered_valid_perm_array
       println(good_perm)
       dupl_of_value = deepcopy(value)
           for jj in 1:length(good_perm)
           dupl_of_value[jj]["price"]["price"] = good_perm[jj]
               if jj == 1
                   println("good: ", dupl_of_value[jj]["price"]["price"])
               end
           end
           println("1 bad: ", dupl_of_value[1]["price"]["price"])
           println("1 bad: ", dupl_of_value[2]["price"]["price"])
       end
[2.0, 10.0, 20.0, 30.0, 40.0]
good: 2.0
1 bad: 2.0
1 bad: 10.0

Are you sure you’re not mistaking something else?

Can you make a minimum working example (MWE) of runnable code that shows the issue you’re concerned about, as described here: Please read: make it easier to help you?

Hi there,

Thanks for your response and the clarification on the MWE. In the process of making and testing the MWE, I’ve fixed my issue and got the code behaving as I need it too. Basically, the issue didn’t have to do with how I made and used the permutations, but with how I constructed the original value variable that dupl_of_value then deep copied (my snippets constructed the original value variable different to how I actually am constructing them hence why for you the code was working; I didn’t think how it was constructed at the time mattered when making my snippets but now I know better from testing and the lesson on MWE). Originally, I assigned index 5 of value to be the same as index 1 without using deepcopy, so this got them to share the same memory address. Thus, when jj hit 5 and dupl_of_value[5][…] was modified, that also resulted in dupl_of_value[1][…] being modified.

Hope that makes some sense, thought I oughta explain what the issue was and how I’ve got it working now that I’ve identified it. Thanks for your help.

1 Like