【问题标题】:Removing surrounding brackets in Math expression PHP删除数学表达式 PHP 中的括号
【发布时间】:2017-06-26 07:24:11
【问题描述】:

我想弄清楚,如何使用 php 删除数学表达式中的括号。

有些情况是:
(A+B)(B+C) 应该保持不变
((((A)))) 应该得到 A
((A
(B+C))) 应该得到 A*(B+C)
(((((B+C)*A)))) 应该得到 (B+C)*A

在任何情况下我都找不到正确的解决方案。使用诸如分配属性之类的数学规则是没有选择的。

我不是在寻找复制粘贴算法,只是一个适合我所有情况的标准。 这是最新的尝试,我尝试了正则表达式等不同的方法,但我没有弄明白。

function removeSurroundingBrackets($str)
{
$res=$str;


if(strcmp($res[0],'(')===0 && strcmp($res[strlen($res)-1],')')===0)
{

    $firstOther=0;
    for(; $firstOther<strlen($str);$firstOther++)
    {
        if(strcmp($str[$firstOther],'(')!==0)
            break;
    }

    $removableCount=0;
    $removableCount=substr_count($str,')',$firstOther)-substr_count($str,'(',$firstOther);
}
return substr($str,$removableCount,-$removableCount);
}

编辑:我找到了解决方案:

function removeSurroundingBrackets($str)
{
    $res=$str;


    while(strcmp($res[0],'(')===0 && strcmp($res[strlen($res)-1],')')===0)
    {
        if($this->checkBrackets(substr($res,1,-1)))
            $res=substr($res,1,-1);
        else
            return $res;

    }
    return $res;
}
function checkBrackets($str)
{
    $currdepth=0;
    foreach(str_split($str) as $char)
    {
        if(strcmp($char,')')===0)
        {
            if($currdepth<=0)
                return false;
            else
                $currdepth--;
        }
        else if(strcmp($char,'(')===0)
            $currdepth++;
    }
    return true;
}

【问题讨论】:

  • 请告诉我们您现在尝试了什么。你会用哪种方式去除括号?然后社区会帮助你。您可以使用正则表达式、字符串提取或或或...
  • 使用正则表达式你可以试试something like this demo
  • @bobblebubble:这是可能的,但不要使用whilepreg_match,您应该使用do...whilepreg_replace 的计数参数。
  • @CasimiretHippolyte 是的,好主意,谢谢!没有想过$count。所以你可以试试like this other demo @MartinB

标签: php regex string parsing math


【解决方案1】:

preg_match:

$pattern = '~\A(?:\((?=([^()]*(?:\((?1)\)[^()]*)*)(\)\2?+)\z))*\K(?(1)\1|.*)~';
if ( preg_match($pattern, $str, $m) ) 
    echo $m[0], PHP_EOL;

这个想法是在字符串的开头使用括号,只要它们是最外面的括号。为了确保它们是最外层的括号,您需要检查它们内部是否总是有一个平衡良好的表达式。

为了消费/计算这些最外层的括号,我使用了这个设计:

\A # from the start of the string
(?: # an eventually repeated non-capturing group
    \(
    (?= # a lookahead to check if the corresponding closing parenthesis exists
        ([^()]*(?:\((?1)\)[^()]*)*) # balanced expression inside
        ( \) \2?+ ) # capture group grows at each non-capturing group repetition
        \z # anchored at the end of the string
    )
)* # since the quantifier is greedy, it will consume all opening parenthesis

那么,您只需要使用\K将匹配结果中的这些括号去掉,并测试捕获组1是否存在:

\K
(?(?1)  # if the capture group 1  exists
    \1  # match its content
     |  # else
     .* # match all the string
)

【讨论】:

【解决方案2】:
function removeSurroundingBrackets($str)
{
$res=$str;


while(strcmp($res[0],'(')===0 && strcmp($res[strlen($res)-1],')')===0)
{
    if($this->checkBrackets(substr($res,1,-1)))
        $res=substr($res,1,-1);
    else
        return $res;

}
return $res;
}
function checkBrackets($str)
{
$currdepth=0;
foreach(str_split($str) as $char)
{
    if(strcmp($char,')')===0)
    {
        if($currdepth<=0)
            return false;
        else
            $currdepth--;
    }
    else if(strcmp($char,'(')===0)
        $currdepth++;
}
return true;
}

【讨论】:

    【解决方案3】:

    单行正则表达式解决方案怎么样:

    $re = "~(?|\({2,}". ( $p = "(\(((?:[^()]*|(?1))*)\))" ) ."\){2,}|^(((\([^()]+\))+))$|$p)~";
    echo preg_replace($re, '$2', $str);
    

    Live demo

    【讨论】:

    • 另外,您在演示中放置了一个不平衡的((((A+B)+C)) 样本,我认为它不应该存在。
    • 不要把这个考虑在内,这是一个错字。 (必须是((((A+B))+C))
    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2021-02-17
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多