Search code examples
phpregexstringreverseparentheses

Reverse the order of parenthetically grouped text and reverse the order of parenthetical groups


I have a strings with pattern, something like this:

(X,1,1,3),(X,1,1,3),(X,@2,@2,@2,@2,@2,(Y,1))

And I need to extract from this One big array, reverse order, and generate new string:

(X,(Y,1),@2,@2,@2,@2,@2),(X,3,1,1),(X,3,1,1)

And expected array:

Array (
    [0] => Array(
        [parent] => (X,1,1,3)
        [childs] => Array(
            [0] => X
            [1] => 1
            [2] => 1
            [3] => 3
        )
    [1] => Array(
        [parent] => (X,1,1,3)
        [childs] => Array(
            [0] => X
            [1] => 1
            [2] => 1
            [3] => 3
        )
    [2] => Array(
        [parent] => (X,@2,@2,@2,@2,@2,(Y,1))
        [childs] => Array(
            [0] => X
            [1] => @2
            [2] => @2
            [3] => @2
            [4] => @2
            [5] => @2
            [6] => (Y,1)
        )
)

For now, I have only first level for parents with this code:

   foreach($datasetxml->Solution->Pattern as $el){

        if(substr( $el["Str"], 0, 1 ) === "L"){

            preg_match_all("/\((((?>[^()]+)|(?R))*)\)/", $el["Str"], $text);

            $text = $text[0];

            $text = array_reverse($text);
            
            foreach($text as $t){            
                //$t = str_replace(")", "", $t);
                $new_texts[] = $t;            
            }        
            $new_text = implode(",", $new_texts);        
            $el["Str"] = $new_text;
        }    

    }

Solution

  • I could reverse you pattern by converting it to JSON, then decode and manipulate it. The code looks like this:

    <?php
    
    function reverseRecursive($array, $recursing = false) {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $array[$key] = '(' . reverseRecursive($value, true) . ')';
            }    
        }
        $first = $recursing ? array_shift($array) . ',' : '';
        return $first . implode(',', array_reverse($array));
    }
    
    $data    = '(X,1,1,3),(X,1,1,3),(X,@2,@2,@2,@2,@2,(Y,1))';
    $json    = preg_replace(['/[^(),]+/', '/\(/', '/\)/'], 
                            ['"$0"', '[', ']'], "($data)");
    $inverse = reverseRecursive(json_decode($json));
    
    echo $inverse;
    

    This results in:

    (X,(Y,1),@2,@2,@2,@2,@2),(X,3,1,1),(X,3,1,1)
    

    A demo can be found here: https://3v4l.org/kISpv

    preg_replace() is used to turn your pattern into JSON. This is then decoded so it can be processed in PHP. The reverseRecursive() does a basic recursive reverse of the array, leaving the first item in place except for the outer array, and implodes it to a string again.

    I don't understand what your "expected array" has to do with this, so I don't know how to answer that part of your question.