0

Good day. I have a parcer function that taker an array of string like this:

['str','str2','str2','*str','*str2','**str2','str','str2','str2']

And recursivelly elevates a level those starting with asterix to get this

['str','str2','str2',['str','str2',['str2']],'str','str2','str2']

And the function is:

function recursive_array_parser($ARRAY) {
 do {
 $i = 0;
 $s = null;
 $e = null;
 $err = false;
 foreach ($ARRAY as $item) {
 if (!is_array($item)) { //if element is not array
 $item = trim($item);
 if ($item[0] === '*' && $s == null && $e == null) { //we get it's start and end if it has asterix
 $s = $i;
 $e = $i;
 } elseif ($item[0] === '*' && $e != null)
 $e = $i;
 elseif (!isset($ARRAY[$i + 1]) || $s != null && $e != null) { //if there are no elements or asterix element ended we elevate it
 $e = $e == NULL ? $i : $e;
 $head = array_slice($ARRAY, 0, $s);
 $_x = [];
 $inner = array_slice($ARRAY, $s, $e - $s + 1);
 foreach ($inner as $_i)
 $_x[] = substr($_i, 1);
 $inner = [$_x];
 $tail = array_slice($ARRAY, $e + 1, 999) or [];
 $X = array_merge($head, $inner);
 $ARRAY = array_merge($X, $tail);
 $s = null;
 $e = null;
 $err = true;
 }
 } else {
 $ARRAY[$i] = recursive_array_parser($ARRAY[$i]); //if the item is array of items we recur.
 }
 $i++;
 if ($err == true) {
 break 1;
 }
 }
 } while ($err);
 return $ARRAY;
}

When this function runs, i get "Fatal error: Maximum function nesting level of '200' reached, aborting!" error.

I know it has something to do with infinite recursion, but i can't track the particular place where it occurs, and this is strange.

asked Jul 22, 2015 at 15:07
5
  • If you have ['*a', 'b', '*c'], should that become ['b', ['a','c']] or [['a'], 'b', ['c']]? Commented Jul 22, 2015 at 15:12
  • i think [[a],b,[c]] because asterics shows level. Am i wrong? Commented Jul 22, 2015 at 15:18
  • @splash58 That appears to be what he is trying to do, but if he wants ['b', ['a', 'c']], this would be much simpler. The error is obviously caused by altering $ARRAY inside the foreach based on $ARRAY while incrementing $i without regard for $ARRAY itself. Commented Jul 22, 2015 at 15:27
  • @kainaw it will be better to hear the autror :)) Commented Jul 22, 2015 at 15:30
  • @splash58 [['a'], 'b', ['c']] Commented Jul 23, 2015 at 6:36

2 Answers 2

2

I don't normally rewrite code, but your code can be reduced and simplified while, from what I can see, getting the desired result. See if this works for you:

$a = array('a','b','c','*d','*e','**f','g','*h');
print_r($a);
$a = recursive_array_parser($a);
print_r($a);
function recursive_array_parser($array)
{
 $ret = array();
 for($i=0; $i<sizeof($array); $i++)
 {
 if($array[$i]{0}!='*') $ret[] = $array[$i];
 else
 {
 $tmp = array();
 for($j=$i; $j<sizeof($array) && $array[$j]{0}=='*'; $j++)
 {
 $tmp[] = substr($array[$j],1);
 }
 $ret[] = recursive_array_parser($tmp);
 $i = $j-1;
 }
 }
 return $ret;
}

Note that it isn't possible for $array[$i] to be an array, so that check is removed. The recursion takes place on the temp array created when a * is found. The $i is closer tied to $array to reset it properly after parsing the series of * elements.

answered Jul 22, 2015 at 15:39
4
  • Cool. it correcty (if i understand rightly) works with [a,****b, *c, d] Commented Jul 22, 2015 at 15:45
  • I just checked to verify. It does work with ['a', '******b', '*c', 'd'] Commented Jul 22, 2015 at 15:55
  • Wow thanks. it's a truly great rewrite. But why wasn't my function working? I mean $ARRAY[$i] = recursive_array_parser($ARRAY[$i]); should take an array, do work with it, and return it in place of the old part. I can't see why it should mess with my function. Commented Jul 23, 2015 at 6:41
  • @НиколайКахневич I didn't run your function to analyze it. Just looking at it, it replaces one instance of a * item with an array, but not all of them. So, [a, *b, *c] becomes [a, [b, c], *c]. See how it replaced *b in place, but it doesn't delete the *c. That is why I used a temp array instead of replacing in-place. Commented Jul 23, 2015 at 15:12
1

Here's my solution. No nested loops.

function recursive_array_parser($arr) {
 $out = array();
 $sub = null;
 foreach($arr as $item) {
 if($item[0] == '*') { // We've hit a special item!
 if(!is_array($sub)) { // We're not currently accumulating a sub-array, let's make one!
 $sub = array();
 }
 $sub[] = substr($item, 1); // Add it to the sub-array without the '*'
 } else {
 if(is_array($sub)) { 
 // Whoops, we have an active subarray, but this thing didn't start with '*'. End that sub-array
 $out[] = recursive_array_parser($sub);
 $sub = null;
 }
 // Take the item
 $out[] = $item;
 }
 }
 if(is_array($sub)) { // We ended in an active sub-array. Add it.
 $out[] = recursive_array_parser($sub);
 $sub = null;
 }
 return $out;
}
answered Jul 22, 2015 at 15:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.