Skip to content
Advertisement

Convert dictionary containing fractions into string

I want to convert a dictionary into a list of strings. Although my actual code is much longer, a MWE is:

>>> import json
>>> mydict = {'c1': (84/255, 0/255, 0/255), 'c2': (15/255, 123/255, 175/255)}
>>> json.dumps(mydict)

The output is:

'{"c1": [0.32941176470588235, 0.0, 0.0], "c2": [0.058823529411764705, 0.4823529411764706, 0.6862745098039216]}'

If I try the fractions package, it seems I can convert fractions themselves into something suitable but it doesn’t work for dictionaries or arrays:

from fractions import Fraction

x = Fraction(84/255).limit_denominator()
print(x)

y = Fraction(np.array([84/255, 0/255])).limit_denominator()
print(y)

z = Fraction(mydict).limit_denominator()
print(z)

I want to extract all the numerical values (while keeping them as fractions) and put them in a list, something like:

mylist = ['(84/255, 0/255, 0/255)', '(15/255, 123/255, 175/255)']

FYI I can’t save the tuples as strings in my actual code (not this MWE) because I’m not allowed to change the particular format. So it’s necessary to convert mydict directly, eg. like str(Fraction({'c1': (84/255, 0/255, 0/255), 'c2': (15/255, 123/255, 175/255)}).limit_denominator().

Advertisement

Answer

If you know that all your fractions have a denominator of 255. You can build a helper method that will iterate through your dictionary building up its own string to display.

Here is an example:

def dump_by_fraction(dictionary: dict):
    output_string = ''
    first_item = True
    for key, faction_list in dictionary.items():
        item_output = ''
        for index, fraction in enumerate(faction_list):
            item_output += (", " if index > 0 else "") + f"{math.floor(fraction * 255)} / 255"
        output_string += ("" if first_item > 0 else ", ") + f"'{key}': [{item_output}]"
        first_item = False
    print('{' + output_string + '}')

you can try calling dump_by_fraction(mydict) instead of json.dumps(mydict)

I would use this for debugging / display purposes only because there can be data loss when converting back and forth between integers and floats.

A simpler solution could be to store the RGB values just as integer and drop the / 255 completely as you will know it’s out of 255.

For Example:

mydict = {'c1': (84, 0, 0), 'c2': (15, 123, 175)}

this way to you eliminate the need to convert completly.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement