0

I have this function for replacing substrings according to a dict:

def unescape(val):
    escaped_dict = {'7D5D':'7D', '7D33':'13', '7D31':'11', '7D5E':'7E'}
    res = val
    for key, value in escaped_dict.items():
        res = res.replace(key, value)
    return res

print(unescape("A20327D5D5D7D5D33"))
>>
A20327D5D13

ok changed 7D5D to 7D, but after it changed 7D33 to 13. I want to replace only once (eg: A20327D5D5D7D33).

The solution would be to add:

if key in val:
    return res

But when there are several or more values from the dict to exchange it won't work.

RedKnite
  • 1,525
  • 13
  • 26
  • Is there a formulas to get replacement from pattern? – ThunderPhoenix Jul 10 '20 at 15:59
  • Replace takes an additional argument `maxreplace`. So `res = res.replace(key, value, 1)` should replace just once. – Maurice Meyer Jul 10 '20 at 16:02
  • If you only want to replace once, use the optional third argument to `replace`: `res = val.replace(key, value, 1)` and return `res` if `res != val`. – chash Jul 10 '20 at 16:03
  • Using [re.sub](https://stackoverflow.com/questions/2400504/easiest-way-to-replace-a-string-using-a-dictionary-of-replacements) – DarrylG Jul 10 '20 at 16:43

1 Answers1

0

The proble in your, is that when you change 7D5D33 to 7D33 in the first iteration, teh result will be changed to 13 in the next iteration because 7D33 is in escaped_dict.keys.

You can for example, change the patterns into not used characters:

def unescape(val):
    escaped_dict = {'7D5D':'__7D__', '7D33':'__13__', '7D31':'__11__', '7D5E':'__7E__'}
    escaped_dict2 = {'__7D__':'7D', '__13__':'13', '__11__': '11', '__7E__': '7E'}
    res = val
    for key, value in escaped_dict.items():
        res = res.replace(key, value)

    # This part could be replaced by the code the update section.
    for key, value in escaped_dict2.items():
        res = res.replace(key, value)
    
    return res

But, I recommand to use re.sub, this is very appropriate here.

Update: re.sub solution

To do the second replacement:

import re
res = re.sub(r"__([\dA-Z]{2})__", r"\1", res)
ThunderPhoenix
  • 1,649
  • 4
  • 20
  • 47