Home > Software design >  Updating nested values incrementally in python
Updating nested values incrementally in python

Time:05-12

There are numerous questions with this sort of title, but they do not really help me. I may even be asking it wrong.

I've got a data structure that looks like this:

dd = {1: [(1, 1, 0, 0), (2, 1, 0, 0), (3, 1, 0, 0)],
      2: [(1, 2, 0, 0), (2, 2, 0, 0), (3, 2, 0, 0)]}

I am attempting to modify the value index 2 in each tuple by an increment starting with zero so as to return:

{1: [(1, 1, 0, 0), (2, 1, 30, 0), (3, 1, 60, 0)],
 2: [(1, 2, 0, 0), (2, 2, 30, 0), (3, 2, 60, 0)]}

So far, I can print the values by doing this but I'm not clear how to actually change the dictionary. I am certainly doing this poorly, and inefficiently; I am not wed to any method so long as it returns the desired data structure:

interval = 30

dd = {1: [(1, 1, 0, 0), (2, 1, 0, 0), (3, 1, 0, 0)],
      2: [(1, 2, 0, 0), (2, 2, 0, 0), (3, 2, 0, 0)]}

for k, v in dd.items()
    dist_from_origin = 0
    for row in v:
        row = list(row)
        row[2] = dist_from_origin
        dist_from_origin  = interval
        row = tuple(row)

Printing shows the row updates but does not update the values in v and in dd itself. Where am I going wrong? How do I compress this down into something that works and doesn't look like hot garbage?

CodePudding user response:

Here's one option with list comprehensions:

{k:[(a,b,30*i,d) for i, (a,b,c,d) in enumerate(v)] for k,v in dd.items()}

What it does is associate an updated list to each element in the dictionary. The updated list will have the same tuples as before with the exception of having in the 3rd position your value 30 multiplied by the index of the tuple inside the list.

CodePudding user response:

When you convert the tuples into lists you are not changing what is in v, you are creating new lists outside of v. So what you would need to do is replace the tuples in v with your newly created tuples.

To fix the code in your question you could try something like this:

interval = 30

dd = {1: [(1, 1, 0, 0), (2, 1, 0, 0), (3, 1, 0, 0)],
      2: [(1, 2, 0, 0), (2, 2, 0, 0), (3, 2, 0, 0)]}

for k, v in dd.items()
    dist_from_origin = 0
    for i, row in enumerate(v):  
        
        # this is taking row and creating a list
        # it does not do anything to the original tuple
        row = list(row)  
        
        row[2] = dist_from_origin
        dist_from_origin  = interval
        row = tuple(row)
        
        # this is the part where you replace the original tuple
        # with the one you just created
        v[i] = row

For a more compact method of doing the same thing take see the answer from @lemon.

  • Related