Home > Blockchain >  Is there a way to replace diferent values in a string?
Is there a way to replace diferent values in a string?

Time:03-02

So i'm trying to replace normal numbers for roman numbers, but only the last number is replaced, so i wonder if there's a way to replace diferent values

sample = "Carl 5, 19 century"
numbers = re.findall(r'[0-9] ', sample)
for number in numbers:
    num_int = int(number)
    roman_number = int_to_Roman(num_int)
    new_string = sample.replace(number, roman_number)

>>> Carl 5, XIX century

Here are some other results

sample = "Carl 19, 19 century"
>>> Carl XIX, XIX century

sample = "Carl 5"
>>> Carl V

CodePudding user response:

The below line in your code is taking the original string sample and replacing the number with the roman_number but it is stored in a variable new_string. In the next iteration, the code will again take the original string (which does not have the previous iteration's replacement stored) and replace the number with roman_number which is why when you are printing the new_string after the loop, it is just showing the last number being replaced (which is the replacement in the last iteration of the loop).

new_string = sample.replace(number, roman_number)

There are 2 fixes for this. One is to store the modified string in the sample variable itself so that the loop can take the result of the last iteration and do further replacements.

sample = sample.replace(number, roman_number)

If you want to retain the original variable sample, you can create a copy of the variable before the loop and do the replacement operation on the new_string variable.

sample = "Carl 5, 19 century"
numbers = re.findall(r'[0-9] ', sample)
new_string = sample
for number in numbers:
    num_int = int(number)
    roman_number = int_to_Roman(num_int)
    new_string = new_string.replace(number, roman_number)

CodePudding user response:

You can use re.sub() and pass a callable (function) to the repl argument. This callable takes one argument -- the match object, and returns the substitution for that match, so it would likely be a simple wrapper that extracts the match string from the match object and passes it on to int_to_Roman:

def int_to_Roman_wrapper(match_obj):
    return int_to_Roman(int(match_obj.group(0)))


sample = 'Carl 5, 15 century' 
new_string = re.sub(r"\d ", int_to_Roman_wrapper, sample)

Which gives new_string = 'Carl V, XV century'

This doesn't have the problem that the str.replace approach does which tdelaney mentions in their comment:

.replace will replace numbers throughout the string even if they are part of a larger number later on. sample = "Carl 5, 15 century" would fail because the 5 in 15 would be replaced on the first match. The second match would try to replace 15, but its already been destroyed

  • Related