Home > Software engineering >  How to multiply numbers in JSON text
How to multiply numbers in JSON text

Time:10-14

I have hundreds of entries on hundreds of files that look like this (numbers not fixed):

"DstQuad":[12,-36,27,-36,27,-23,12,-23],"SrcQuad":[493,95,508,95,508,108,493,108]

The relevant portion of the files look like this, repeated hundreds of times, with no lines, just a continuous string:

{"TexID":0,"DstQuad":[-24,-23,-1,-23,-1,6,-24,6],"SrcQuad":[61,240,84,240,84,269,61,269]},{"TexID":0,"DstQuad":[-11,-73,36,-73,36,-45,-11,-45],"SrcQuad":[87,240,134,240,134,268,87,268]},

I need to be able to tell when a number is inside that structure, then take each number and multiply it, while leaving numbers not in that structure alone.

Tried adapting a script I found, but it doesn't do anything:

def multiply_numbers_in_context(match):
#   return "{0}{1}{2}".format(match.group(1), str(float(match.group(2))*4), '"')
    return "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}{16}".format(match.group(1), str(int(match.group(2))*4), ',', str(int(match.group(3))*4), ',', str(int(match.group(4))*4), ',', str(int(match.group(5))*4), ',', str(int(match.group(6))*4), ',', str(int(match.group(7))*4), ',', str(int(match.group(8))*4), ',', str(int(match.group(9))*4), ',', match.group(10), ',',  str(int(match.group(11))*4), ',', str(int(match.group(12))*4), ',',  str(int(match.group(13))*4), ',', str(int(match.group(14))*4), ',', str(int(match.group(15))*4), ',', str(int(match.group(16))*4), ']')

editor.rereplace(r'("DstQuad":[)(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d )(],"SrcQuad":[)(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d ),(-?\d )(])', multiply_numbers_in_context)

Help would be greatly appreciated.

CodePudding user response:

I'd suggest using the json module for this. Here's a simple example with loading a JSON string and using object_hook to multiply each list element by a constant value (4 in this case). The result string is a JSON string that can then be saved to a file.

I also made a few assumptions about your use case:

  • The contents of the file can be represented as a list [] that contains a bunch of dictionaries {} with the useful data
  • All nested lists [] that contain numbers should have all their elements multipled by a constant value (of 4 in this case)
import json

file_contents = """
[
    {"TexID":0,"DstQuad":[-24,-23,-1,-23,-1,6,-24,6],"SrcQuad":[61,240,84,240,84,269,61,269]},
    {"TexID":0,"DstQuad":[-11,-73,36,-73,36,-45,-11,-45],"SrcQuad":[87,240,134,240,134,268,87,268]}
]
"""


def hook_fn(value, multiplier=4):
    if isinstance(value, list) and value and isinstance(value[0], (int, float)):
        return [elem * multiplier for elem in value]
    if isinstance(value, dict):
        return {k: hook_fn(v) for k, v in value.items()}
    return value


string = json.dumps(json.loads(file_contents, object_hook=hook_fn))
print(string)
# [{"TexID": 0, "DstQuad": [-96, -92, -4, -92, -4, 24, -96, 24], "SrcQuad": [244, 960, 336, 960, 336, 1076, 244, 1076]}, {"TexID": 0, "DstQuad": [-44, -292, 144, -292, 144, -180, -44, -180], "SrcQuad": [348, 960, 536, 960, 536, 1072, 348, 1072]}]

To read and write from a text file instead, use json.load and json.dump instead (drop the s at the end):

with open('input.txt') as in_file:
    data = json.load(in_file, object_hook=hook_fn)


with open('output.txt', 'w') as out_file:
    json.dump(data, out_file)
  • Related