Click here to Skip to main content
15,887,477 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I have a string that contains words and one or more roman numerals from one (I) to ten (X).
I need to replace those numerals with integers.

This is what I tried:
PHP
$reps = [
'I' => 1,
'II' => 2,
'III' => 3,
'IV' => 4,
'V' => 5,
'VI' => 6,
'VII' => 7,
'VIII' => 8,
'IX' => 9,
'X' => 10
];

$str = "word word VII word ...";

$str2 = str_replace(array_keys($reps), $reps, $str);

But it doesn't work: "VII" is replaced by "511" instead of "7".

How can I fix it?

What I have tried:

PHP
$reps = [
'I' => 1,
'II' => 2,
'III' => 3,
'IV' => 4,
'V' => 5,
'VI' => 6,
'VII' => 7,
'VIII' => 8,
'IX' => 9,
'X' => 10
];

$str = "word word VII word ...";

$str2 = str_replace(array_keys($reps), $reps, $str);
Posted

As documented at PHP: str_replace - Manual[^], str_replace() matches from first to last.
To do what you want, you need to put all search strings BEFORE any prefixes of them, so an order like
IV IX III II I VIII VII VI V X
should work.
 
Share this answer
 
Comments
CPallini 6-Feb-24 2:32am    
I bet it does.
Peter_in_2780 6-Feb-24 4:55am    
:) Thanks, Carlo.
LB2371 6-Feb-24 2:55am    
Isn't there a way to treat each roman numeral as a word and do a whole-word replacement? Maybe using "preg_replace" or "preg_replace_callback"?
Peter_in_2780 6-Feb-24 4:54am    
Yes that would work, and so would including a trailing space in the match string if you want to stick with str_replace.
Your choice really comes down to what you want to do with edge cases, like a "word" starting with I, or the roman number at the start or end of input, and so on.
LB2371 10-Feb-24 5:33am    
Your "empirical" solution doesn't work for me: for example, "VII" is replaced by "52" (instead of "7"). See my own solution below.
In addition to the above and your comment -

Your problem is that 'str_replace' performs replacements in the order they appear in your array as mentioned above. You can use the 'strtr' function (PHP strtr Function[^]) along with a custom replacement function to return the correct replacement, tested with all array items in W3Schools Editor[^] -

HTML
<!DOCTYPE html>
<html>
<body>

<?php
$reps = [
    'I' => 1,
    'II' => 2,
    'III' => 3,
    'IV' => 4,
    'V' => 5,
    'VI' => 6,
    'VII' => 7,
    'VIII' => 8,
    'IX' => 9,
    'X' => 10
];

$str = "word word IX word ...";

function replaceNumerals($matches) {
    global $reps;
    return $reps[$matches[0]];
}

$str2 = preg_replace_callback('/\b(?:' . implode('|', array_map('preg_quote', array_keys($reps))) . ')\b/', 'replaceNumerals', $str);

print_r($str2);
?>

</body>
</html>


Returns 'word word 9 word ...'
 
Share this answer
 
Comments
LB2371 6-Feb-24 13:19pm    
Where's the "strtr" function in your code?
Andre Oosthuizen 7-Feb-24 15:24pm    
If you follow the link provided you will notice that I have modified the code a little to conform to that will work for you...
PHP
$nums = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'];
$str = preg_replace_callback('/\b(I|II|III|IV|V|VI|VII|VIII|IX|X)\b/', fn($m) => array_search($m[0], $nums) +1, $str);

// $str = preg_replace_callback('/\b('.implode('|', $nums).')\b/', fn($m) => array_search($m[0], $nums) +1, $str);
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900