geudrik Posted June 26, 2012 Share Posted June 26, 2012 I have a large multidimensional array that can exist of any number of Children arrays, each having the potential to have any number of their own children (though, realistically not to exceed a few layers deep before actual values being to appear) For example, my array might look something like this... Array ( [Ford] => Array ( [Mustang] => Array ( [seats] => Array ( [0] => Leather [1] => Cloth ) [Trim] => Array ( [0] => Plastic [1] => Wood ) ) [F-150] => Array ... ) [Honda] => Array ... ) What I'm trying to do is traverse the array to the lowest child and work backwards. For example, I'm trying to create a single string (or series of strings) similar to the following Ford/Mustang/Seats/Leather Ford/Mustang/Seats/Cloth Ford/Mustang/Trim/Wood Ford/Mustang/Trim/Plastic Ford/F-150/.. .... What would be the easiest way to go about this? Making a function, testing if the child is an array and recalling the function from within the function, until it hits a key value that isn't an array, then walking backwards? That seems the most logical to me, but then I run into the issue of trying to combine Key names to Key values. Thoughts and/or suggestions? Quote Link to comment Share on other sites More sharing options...
Zane Posted June 26, 2012 Share Posted June 26, 2012 What would be the easiest way to go about this? Making a function, testing if the child is an array and recalling the function from within the function, until it hits a key value that isn't an array, then walking backwards? Yep, Ideally, you'd use a foreach loop. and a string variable ... as well as a recursive function UNTESTED $multdimarray = array(); $stringVar = null; function createString($arr, &$str) { foreach($arr $k => $v) { if(is_array($v)) { $str .= $k . "/"; createString($v, $str); } else { $str .= $v; } } } // Then call it $mystring($multidimarray, $stringVar); // $stringVar will have your stuff. Quote Link to comment Share on other sites More sharing options...
geudrik Posted June 26, 2012 Author Share Posted June 26, 2012 Alright, I figured that'd be easiest. One question about your suggestion though - what does this represent? foreach($arr $k => $v) $arr is the multidim array, but I've never used foreach() like this before. Can you give me a brief synopsis of what's you're doing here? Never mind, I RTFM'd Quote Link to comment Share on other sites More sharing options...
geudrik Posted June 26, 2012 Author Share Posted June 26, 2012 Fundamentally, I have the parser working. However what isn't working is how it creates the string in the end. It, for each array, creates a string that is a concatenation of the entire Toplevel parent array. Suggestions to circumvent this? There several elements in the lowest level children arrays. For each one of those elements, the string portion before the element values needs to remain static. Once the child array has been exhausted of all values, the process repeats, starting one level higher. This is what I'm going after... Ford/Mustang/Seats/Leather Ford/Mustang/Seats/Cloth Ford/Mustang/Trim/Wood Ford/Mustang/Trim/Plastic Ford/F-150/.. This is what I get... Ford/Mustang/Seats/Leather Ford/Mustang/Seats/LeatherCloth Ford/Mustang/Seats/LeatherClothWood ... Setting the string value to null at the end of the loop doesn't work, as then it loses its current path information, and winds up just dumping the element value of the child array it's walking. Thoughts? PS: Thanks Zane for the usage of the amprisand - I had no idea that it had that functionality! Quote Link to comment Share on other sites More sharing options...
Zane Posted June 26, 2012 Share Posted June 26, 2012 I'll have to ponder of that for a second. You need a counting variable to show that you've reached the end of an array, I'm just not entirely sure where it should go at the moment. :?: Quote Link to comment Share on other sites More sharing options...
geudrik Posted June 27, 2012 Author Share Posted June 27, 2012 I was thinking that maybe the best way to do it would be to keep track of where the script is in the array, using an index array of numeric values that essentially is just a list. eg: $counter = array(1,2,3,4); And on the fly, just reconstruct the string based on Key/Value names when requested by the string output. This clearly is a very inefficient way to do it, but it's about the best idea I've got, given my knowledge... :-\ The first issue I foresee though is keeping the array alive/making it available to the child of the function when it spawns itself on each child array... Quote Link to comment Share on other sites More sharing options...
xyph Posted June 27, 2012 Share Posted June 27, 2012 Here's my take. I use array_merge and a recursive function <?php $array = array( 'mustang' => array( 'seats' => array('leather','cloth'), 'trim' => array('plastic','wood') ), 'f150' => array( 'seats' => array('leather','cloth'), 'trim' => array('plastic','wood'), 'deeper' => array( 'foo' => array('deep','stuff'), 'bar' => array('goes','here') ) ), 'fiesta' => array( 'engine' => 'tiny' ), 'pinto' => 'don\'t drive' ); var_dump( flatten($array) ); function flatten( $array, $divide = '/', $str = FALSE) { $return = array(); foreach( $array as $k => $v ) { if( is_array($v) ) $return = array_merge($return,flatten($v,$divide,$str.$k.$divide)); else $return[] = $str.$v; } return $return; } ?> result array 0 => string 'mustang/seats/leather' (length=21) 1 => string 'mustang/seats/cloth' (length=19) 2 => string 'mustang/trim/plastic' (length=20) 3 => string 'mustang/trim/wood' (length=17) 4 => string 'f150/seats/leather' (length=18) 5 => string 'f150/seats/cloth' (length=16) 6 => string 'f150/trim/plastic' (length=17) 7 => string 'f150/trim/wood' (length=14) 8 => string 'f150/deeper/foo/deep' (length=20) 9 => string 'f150/deeper/foo/stuff' (length=21) 10 => string 'f150/deeper/bar/goes' (length=20) 11 => string 'f150/deeper/bar/here' (length=20) 12 => string 'fiesta/tiny' (length=11) 13 => string 'don't drive' (length=11) As you can see, it kinda screws up on single-depth named keys. It's possible to fix this, by checking if the key's numeric, or having a flag off for the initial call, and on during recursion. Figured it wasn't a big deal though. Leave $str as FALSE when calling, unless you want some prefix value in front of each result. Quote Link to comment Share on other sites More sharing options...
Barand Posted June 27, 2012 Share Posted June 27, 2012 here's mine <?php $spec = Array ( 'Ford' => Array ( 'Mustang' => Array ( 'Seats' => Array ( '0' => 'Leather', '1' => 'Cloth' ), 'Trim' => Array ( '0' => 'Plastic', '1' => 'Wood' ) ), 'Focus' => Array ( 'Seats' => Array ( '1' => 'Cloth' ), 'Trim' => Array ( '0' => 'Plastic', ) ) ), 'BMW' => Array ( '5 series' => Array ( 'saloon' => array ( 'Seats' => Array ( '0' => 'Leather', '1' => 'Cloth' ), 'Trim' => Array ( '0' => 'Plastic', '1' => 'Walnut' ) ), 'coupe' => array ( 'Seats' => Array ( '0' => 'Leather', '1' => 'Cloth' ), 'Trim' => Array ( '0' => 'Plastic', '1' => 'Walnut' ) ) ) ) ); $results = array(); getSpec($spec, '', $results); echo '<pre>'.print_r($results, 1).'</pre>'; function getSpec($arr, $str, &$results) { foreach ($arr as $k => $v) { if (is_array($v)) { getSpec($v, $str.$k.'/', $results); } else { $results[] = $str.$v; } } } ?> RESULTS--> Array ( [0] => Ford/Mustang/Seats/Leather [1] => Ford/Mustang/Seats/Cloth [2] => Ford/Mustang/Trim/Plastic [3] => Ford/Mustang/Trim/Wood [4] => Ford/Focus/Seats/Cloth [5] => Ford/Focus/Trim/Plastic [6] => BMW/5 series/saloon/Seats/Leather [7] => BMW/5 series/saloon/Seats/Cloth [8] => BMW/5 series/saloon/Trim/Plastic [9] => BMW/5 series/saloon/Trim/Walnut [10] => BMW/5 series/coupe/Seats/Leather [11] => BMW/5 series/coupe/Seats/Cloth [12] => BMW/5 series/coupe/Trim/Plastic [13] => BMW/5 series/coupe/Trim/Walnut ) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.