【问题标题】:Roman numerals to numbers in string罗马数字到字符串中的数字
【发布时间】:2018-07-19 10:19:17
【问题描述】:

我有这个字符串:

$string = 'Hello IV WorldX';

我想将所有罗马数字替换为整数。

我有以下函数将罗马转换为整数:

function roman2number($roman){
    $conv = array(
        array("letter" => 'I', "number" => 1),
        array("letter" => 'V', "number" => 5),
        array("letter" => 'X', "number" => 10),
        array("letter" => 'L', "number" => 50),
        array("letter" => 'C', "number" => 100),
        array("letter" => 'D', "number" => 500),
        array("letter" => 'M', "number" => 1000),
        array("letter" => 0, "number" => 0)
    );
    $arabic = 0;
    $state = 0;
    $sidx = 0;
    $len = strlen($roman);

    while ($len >= 0) {
        $i = 0;
        $sidx = $len;
        while ($conv[$i]['number'] > 0) {
            if (strtoupper(@$roman[$sidx]) == $conv[$i]['letter']) {
                if ($state > $conv[$i]['number']) {
                    $arabic -= $conv[$i]['number'];
                } else {
                    $arabic += $conv[$i]['number'];
                    $state = $conv[$i]['number'];
                }
            }
            $i++;
        }
        $len--;
    }
    return($arabic);
}

echo roman2number('IV');

效果很好(在ideone 上试试)。如何通过字符串搜索和替换以替换罗马数字的 all 实例。比如:

$string = romans_to_numbers_in_string($string);

听起来需要正则表达式来拯救......或者?

【问题讨论】:

  • 你的意图不清楚。您是否正在寻找当前方法的正则表达式版本?
  • @revo 否。上面的 php 函数将罗马数字的单个实例转换为像 roman2number('IV') 这样的数字...我想将 all 罗马数字转换为文本字符串,例如romans_to_numbers_in_string('hello IV what X');,这意味着我无法检测字符串中的哪些特定字符是罗马数字以及如何仅转换字符串的这些部分。这有意义吗?
  • 试试$str = preg_replace_callback('~\b[IVXLCDM0]+\b~', function($m) { return roman2number($m[0]); }, $str);。在此处查看现场演示3v4l.org/Q1IHC
  • 不知道你打算把I转换成I know,会转换成1,对吧?您可能需要先用一些形态句法分析器标记输入,然后只替换应该替换的内容。另外,已经有一篇关于匹配Roman numerals in text的好帖子,只需使用单词边界,~\bM{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b~
  • @revo 似乎是该正则表达式的问题。请参阅ideone.com/oQoh40 另外,请注意罗马数字与其他术语之间应有空格。所以HelloX 中的X 不应该匹配,但Hello X 应该匹配。

标签: php regex roman-numerals


【解决方案1】:

这是一个匹配罗马数字的简单正则表达式:

\b[0IVXLCDM]+\b

所以,你可以像这样实现 romans_to_numbers_in_string:

function romans_to_numbers_in_string($string) {
    return preg_replace_callback('/\b[0IVXLCDM]+\b/', function($m) {
           return roman2number($m[0]);
           },$string);
}

这个正则表达式存在一些问题。比如,如果你有这样的字符串:

I like roman numerals

它会变成:

1 like roman numerals

根据您的要求,您可以顺其自然,也可以修改正则表达式,使其不会将单个 I 转换为数字。

【讨论】:

  • 您至少应该在模​​式中使用单词边界以避免匹配较长的单词(例如大写单词)。
  • 你测试了吗? preg_replace不能使用回调,必须使用preg_replace_callback
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多