0

I have been trying to replace integer components of a dictionary with string values given in another dictionary. However, I am getting the following error:

Traceback (most recent call last):


File "<string>", line 11, in <module>
  File "/usr/lib/python3.11/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 14 (char 13)

The code has been given below. Not sure why I am getting an error.

import re 
from json import loads, dumps

movable = {"movable": [0, 3, 6, 9], "fixed": [1, 4, 7, 10], "mixed": [2, 5, 8, 11]}
int_mapping = {0: "Ar", 1: "Ta", 2: "Ge", 3: "Ca", 4: "Le", 5: "Vi", 6: "Li", 7: "Sc", 8: "Sa", 9: "Ca", 10: "Aq", 11: "Pi"}

movable = dumps(movable)
for key in int_mapping.keys():
    movable = re.sub('(?<![0-9])' + str(key) + '(?![0-9])', int_mapping[key], movable)
    
movable = loads(movable)

I understand that this code can easily be written in a different way to get the desired output. However, I am interested to understand what I am doing wrong.

1
  • 1
    Print movable after you transformed it and see how it lacks all quotes around the strings. Anyway, you should probably work on the dict directly... Commented Feb 8, 2023 at 17:46

2 Answers 2

2

If you print how movable looks like right before calling json.loads, you'll see what the problem is:

for key in int_mapping.keys():
    movable = re.sub('(?<![0-9])' + str(key) + '(?![0-9])', int_mapping[key], movable)
print(movable)

outputs:

{"movable": [Ar, Ca, Li, Ca], "fixed": [Ta, Le, Sc, Aq], "mixed": [Ge, Vi, Sa, Pi]}

Those strings (Ar, Ca...) are not quoted, therefore it is not valid JSON.

If you choose to continue the way you're going, you must add the ":

movable = re.sub(
    '(?<![0-9])' + str(key) + '(?![0-9])', 
    '"' + int_mapping[key] + '"', 
    movable)

(notice the '"' + int_mapping[key] + '"')

Which produces:

{"movable": ["Ar", "Ca", "Li", "Ca"], "fixed": ["Ta", "Le", "Sc", "Aq"], "mixed": ["Ge", "Vi", "Sa", "Pi"]}

This said... you are probably much better off by just walking the movable values and substituting them by the values in int_mapping. Something like:

mapped_movable = {}
for key, val in movable.items():
    mapped_movable[key] = [int_mapping[v] for v in val]
print(mapped_movable)
Sign up to request clarification or add additional context in comments.

Comments

1

You could use a dict comprehension and make the mapping replacements directly in Python:

...
movable = {
    k: [int_mapping[v] for v in values]
    for k, values in movable.items()
}
print(type(movable))
print(movable)

Out:

<type 'dict'>
{'mixed': ['Ge', 'Vi', 'Sa', 'Pi'], 'fixed': ['Ta', 'Le', 'Sc', 'Aq'], 'movable': ['Ar', 'Ca', 'Li', 'Ca']}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.