skip to Main Content

I’m trying to one by one, go through each json object and subtract 1 from each value, but I’m not sure where to start…resources on this specific thing are scarce online so I came here…

{
  "12345678910":32,
  "10987654321":21  // after one loop will change to 31 and 20
}
json_file=json.load(file)

for object in json_file:
    # subtract 1 from value

2

Answers


  1. You can leverage Python typing module to accomplish this complex task. doctest too! Comments for explanation!

    import typing
    
    # A generic type. Why working only with `str`s as keys?
    T = typing.TypeVar('T')
    
    # A protocol type. Why working only with `int`s as keys?
    # Work with *anything* that is subtractable by ints:
    class IntSubtractable(typing.Protocol):
        def __sub__(self, value: int) -> IntSubtractable:
            pass
    
    def minus(x: dict[T, IntSubtractable], v: int) -> dict[T, IntSubtractable]:
        """
        Returns a new dictionary where all the values from
        the input dictionary [x] are subtracted by [v].
        
        >>> minus({'a': 1, 'b': 2})
        {'a': 0, 'b': 1}
        >>> minus({True: 3, False: 5})
        {True: 2, False: 4}
        """
        y: dict[T, IntSubtractable] = x
        for key, value in x.items():
            y[key] = value - v
        return y
    
    # The main function. This is where your program runs!
    def main():
        # The input data. `json.load` as an exercise
        # for the reader (you already know it!)
        data = {
          "12345678910": 32,
          "10987654321": 21,
        }
        # Call the function that will subtract 1 for 
        # each value in the input dictionary (`data`)
        updated_data = minus(data, 1)
    
        print(updated_data)
        # The output data. `json.dump` as an exercise
        # for the reader (do you know it?)
        
    # You can use this to avoid external imports
    # to automatically running your script
    if __name__ == '__main__':
        main()
    

    Some users commented that the above function was too overcomplicated. Maybe with recursion the solution becomes more clear:

    import typing
    
    # A generic type. Why working only with `str`s as keys?
    K = typing.TypeVar('K')
    # Another generic type. Why working only with `int`s as values?
    V = typing.TypeVar('V')
    
    
    # A protocol type. Works with *anything* that is
    # subtractable by another type.
    class Subtractable(typing.Generic[V], typing.Protocol):
        def __sub__(self, value: V) -> 'Subtractable[V]':
            pass
    
    # The first overload for the core function. You'll use this.
    @typing.overload
    def minus(
        iterator: typing.Iterator[tuple[K, Subtractable[V]]],
        value: V,
    ) -> dict[K, Subtractable[V]]:
        ...
        
    # The second overload for the core function. We'll use that.
    @typing.overload
    def minus(
        iterator: typing.Iterator[tuple[K, Subtractable[V]]],
        value: V,
        accumulator: dict[K, Subtractable[V]] | None,
    ) -> dict[K, Subtractable[V]]:
        ...
    
    # The core function.
    def minus(
        iterator: typing.Iterator[tuple[K, Subtractable[V]]],
        value: V,
        accumulator: dict[K, Subtractable[V]]  | None= None,
    ) -> dict[K, Subtractable[V]]:
        """
        Returns a dictionary where all the values from
        the input iterator [iterator] are subtracted by [value].
        
        > minus(iter({'a': 1, 'b': 2}.items()), 1)
        {'a': 0, 'b': 1}
        > minus(iter({True: 3, False: 5}.items()), 2)
        {True: 1, False: 3}
        """
        output = {} if accumulator is None else accumulator
        
        # Check if there is a new value for us to subtract
        item = next(iterator, None)
        if item is None:
            # If there is none, return what we have 
            # already subtracted
            return output
        
        # Otherwise, extract the current key and value
        key, current_value = item
        # Subtract it!
        output[key] = current_value - value
        # Call the function again. I love recursion!
        return minus(iterator, value, output)
    
    # The main function. This is where your program runs!
    def main():
        # The input data. `json.load` as an exercise
        # for the reader (you already know it!)
        data = {
          "12345678910": 32,
          "10987654321": 21,
        }
        # Call the function that will subtract 1 for 
        # each value in the input dictionary (`data`)
        updated_data = minus(iter(data.items()), 1)
    
        print(updated_data)
        # Outputs
        # {
        #   "12345678910": 31,
        #   "10987654321": 20,
        # }
        
    # You can use this to avoid external imports
    # to automatically running your script
    if __name__ == '__main__':
        main()
    
    Login or Signup to reply.
  2. You’re almost there. Inside the for loop you just need to

    json_file[object] -= 1
    

    and then:

    json.dump(file, json_file)
    

    Full code:

    with open('file.json', 'r') as file:
        json_file=json.load(file)
    
    for object in json_file:
        # subtract 1 from value
        json_file[object] -= 1
    
    with open('file.json', 'w') as file:
        json.dump(json_file, file)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search