Reputation: 25
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;
}
}
Upvotes: 1
Views: 121
Reputation: 16751
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.
Upvotes: 1
Reputation: 48031
I don't know how well this will hold up on varied input, but it is designed to be recursive in its splitting, reversing, imploding behavior while preserving the first entry's position in each parenthetical group.
The first regex isolates the parent level parenthetical segments and removes the outer parentheses. The second regex isolates the children on the next level. The first child is separated because it is not to be repositioned. Any remaining children are potentially recursively processed, then all children are reversed and appended to the first child. Finally, all parent level segments (with their reversed children) have their order reversed and are re-wrapped with parentheses.
I am fairly confident that this task is going to be too niche to help other developers.
Code: (Demo)
function rSplitReverse($string) {
preg_match_all("/\(((?:(?>[^()]+)|(?R))*)\)/", $string, $matches);
foreach ($matches[1] as &$m) {
if (preg_match_all("/(\((?:(?>[^()]+)|(?R))*\))|[^(),]+/", $m, $items, PREG_SET_ORDER)) {
$first = array_shift($items)[0];
foreach ($items as &$item) {
$item = isset($item[1]) ? rSplitReverse($item[0]) : $item[0];
}
$m = "$first," . implode(',', array_reverse($items));
}
}
return '(' . implode('),(', array_reverse($matches[1])) . ')';
}
echo rSplitReverse('(X,1,1,3),(X,1,1,3),(X,@2,@2,@2,@2,@2,(Y,1))');
// (X,(Y,1),@2,@2,@2,@2,@2),(X,3,1,1),(X,3,1,1)
Upvotes: 1