This is a discussion on Converting string representation of a directory to multi-dimensional array within the PHP General forums, part of the PHP Programming Forums category; Over the weekend, I was tasked with taking a string representation of a directory ('\Interface\Addons\<some dir>\&...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
Over the weekend, I was tasked with taking a string representation of a directory ('\Interface\Addons\<some dir>\<some file>'), which can vary in length (no set number of depths) to a multi-dimensional array (i.e. array('Interface' => array('Addons' => array('<some dir>' => <somefile>)));).
We came up with a very ugly hack to do it, but I'm curious if anyone can help us wrap our head around a better solution, without using eval (which we were able to find that solution quickly, but do not want to use eval).. Our situation is a little unique in the fact that these files don't actually exist on a filesystem, so it makes it a bit more tough to actuallycreate this array. Thanks for any help you can give in cleaning this up somewhat. Here is the function we currently use: <?php $array = array(); addToList('\interface\addons\clearfont\clearfont.t oc2', $array); addToList('\interface\addons\clearfont\clearfont.t oc3', $array); addToList('\interface\addons\clearfont\clearfont.t oc4', $array); addToList('\interface\addons\clearfont\clearfont.t oc5', $array); addToList('\interface\addons\clearfont\subdir\some thing.toc', $array); functionaddToList($str, &$array) { $things = explode('\\', $str); if($things['0'] == '') { array_shift($things); } addToArray($things, $array); } function addToArray($things, &$array) { $count = count($things); switch ($count) { case '1': $array[$things['0']] = $array(); break; case '2': $array[$things['0']][$things['1']] = $things['1']; break; case '3': $array[$things['0']][$things['1']][$things['2']] = $things['2']; break; case '4': $array[$things['0']][$things['1']][$things['2']][$things['3']] = $things['3']; break; <<previous code repeated down to 10>> default: break; } } print_r($array); ?> |
|
|||
|
Matt Carlson wrote:
> Over the weekend, I was tasked with taking a string representation of a directory ('\Interface\Addons\<some dir>\<some file>'), which can vary in length (no set number of depths) to a multi-dimensional array (i.e. array('Interface' => array('Addons' => array('<some dir>' => <somefile>)));). > > We came up with a very ugly hack to do it, but I'm curious if anyone can help us wrap our head around a better solution, without using eval (which we were able to find that solution quickly, but do not want to use eval). > > Our situation is a little unique in the fact that these files don't actually exist on a filesystem, so it makes it a bit more tough to actually create this array. > > Thanks for any help you can give in cleaning this up somewhat. > > Here is the function we currently use: based on an answer to an old post ... below shows how to uses references to walk 'into' an array and set/create multilevel elements - given a bit of thought you should be able to figure out how to apply the concept to your own problem: <?php $ref = null; $keys = array("six","five","four","three","two","one"); $val = "string value"; // the node value $arr = array(); // generated array $ref =& $arr; while ($key = array_pop($keys)) { $ref[$key] = array(); $ref =& $ref[$key]; } $ref = $val; var_dump($arr); |
|
|||
|
On Mon, February 5, 2007 12:27 pm, Matt Carlson wrote:
> Over the weekend, I was tasked with taking a string representation of > a directory ('\Interface\Addons\<some dir>\<some file>'), which can > vary in length (no set number of depths) to a multi-dimensional array > (i.e. array('Interface' => array('Addons' => array('<some dir>' => > <somefile>)));). > > We came up with a very ugly hack to do it, but I'm curious if anyone > can help us wrap our head around a better solution, without using eval > (which we were able to find that solution quickly, but do not want to > use eval). > > Our situation is a little unique in the fact that these files don't > actually exist on a filesystem, so it makes it a bit more tough to > actually create this array. > > Thanks for any help you can give in cleaning this up somewhat. > > Here is the function we currently use: > > <?php > > $array = array(); > > addToList('\interface\addons\clearfont\clearfont.t oc2', $array); > addToList('\interface\addons\clearfont\clearfont.t oc3', $array); > addToList('\interface\addons\clearfont\clearfont.t oc4', $array); > addToList('\interface\addons\clearfont\clearfont.t oc5', $array); > addToList('\interface\addons\clearfont\subdir\some thing.toc', $array); function addToList($path){ $parts = explode('\\', $path); $result = array(); $parts = array_reverse($parts); foreach($parts as $part){ //something with array_splice here... $result = array_splice(array($result), $part); //??? } } -- Some people have a "gift" link here. Know what I want? I want you to buy a CD from some starving artist. http://cdbaby.com/browse/from/lynch Yeah, I get a buck. So? |
|
|||
|
Richard Lynch wrote:
> On Mon, February 5, 2007 12:27 pm, Matt Carlson wrote: >> Over the weekend, I was tasked with taking a string representation of >> a directory ('\Interface\Addons\<some dir>\<some file>'), which can >> vary in length (no set number of depths) to a multi-dimensional array >> (i.e. array('Interface' => array('Addons' => array('<some dir>' => >> <somefile>)));). >> >> We came up with a very ugly hack to do it, but I'm curious if anyone >> can help us wrap our head around a better solution, without using eval >> (which we were able to find that solution quickly, but do not want to >> use eval). >> >> Our situation is a little unique in the fact that these files don't >> actually exist on a filesystem, so it makes it a bit more tough to >> actually create this array. >> >> Thanks for any help you can give in cleaning this up somewhat. >> >> Here is the function we currently use: >> >> <?php >> >> $array = array(); >> >> addToList('\interface\addons\clearfont\clearfont.t oc2', $array); >> addToList('\interface\addons\clearfont\clearfont.t oc3', $array); >> addToList('\interface\addons\clearfont\clearfont.t oc4', $array); >> addToList('\interface\addons\clearfont\clearfont.t oc5', $array); >> addToList('\interface\addons\clearfont\subdir\some thing.toc', $array); > > function addToList($path){ > $parts = explode('\\', $path); > $result = array(); > $parts = array_reverse($parts); > foreach($parts as $part){ > //something with array_splice here... > $result = array_splice(array($result), $part); //??? array_splice won't cut it as it only splices at 1 level, unless I misunderstood the OP is looking to dynamically build a multilevel array - which means either using recursion or 'reference based array digging' (as I like to call it ;-) there may also be some kind of solution based on ArrayArrayArrayIteratorIteratorRecursiveArrayItera torIteratorRecursiveIterator but personally I don't grok those exotic forms of SPL interface well enough to tell you. > } > } > |
|
|||
|
# jochem@iamjochem.com / 2007-02-06 12:45:22 +0100:
> there may also be some kind of solution based on > ArrayArrayArrayIteratorIteratorRecursiveArrayItera torIteratorRecursiveIterator > but personally I don't grok those exotic forms of SPL interface well > enough to tell you. I had wanted to post something when the thread started, but gave up, because I quickly ran into ambiguities. What should the conversion do when given a basename, e. g. addToList("file.txt", ...)? Anyway, here's an implementation, and a few Testilence tests. The code doesn't provide for iteration since, AFAICT, the OP is looking for a map, not an iterable collection. <?php class pata implements ArrayAccess { function __construct($path, $sep = '/') { $this->sep = $sep; $path = trim($path, $sep); if ($this->isBasename($path)) { throw new InvalidArgumentException; } list($key, $rest) = $this->split($path); $this->key = $key; if ($this->isBasename($rest)) { $this->data = $rest; } else { $this->data = new self($rest, $sep); } } function __toString() { return $this->key . $this->sep . $this->data; } function offsetExists($key) { return $this->key === $key; } function offsetGet($key) { return $this->data; } function offsetUnset($key) { throw new LogicException; } function offsetSet($key, $value) { throw new LogicException; } private function isBasename($path) { return (false === strpos($path, $this->sep)); } private function split($path) { $sp = $this->strpos($path, $this->sep); $key = substr($path, 0, $sp); $rest = trim(substr($path, $sp), $this->sep); return array($key, $rest); } private function strpos($haystack, $needle) { $rv = strpos($haystack, $needle); return (false === $rv) ? strlen($haystack) : $rv; } private $key, $data = array(); } class pata_SingleSegmentTest extends Tence_TestCase { function testThrowsOnBaseName() { $this->willThrow('InvalidArgumentException'); new pata('foo'); } } abstract class pata_MultipleSegmentTest extends Tence_TestCase { abstract protected /* string */ function separator(); function setUp() { $this->garbage = 'garbage'; $this->key = 'foo'; $segments = array('bar', 'baz'); $sep = $this->separator(); $this->path = implode($sep, $segments); $this->pata = new pata($this->key . $sep . $this->path, $sep); } function testIssetWithPathAsKeySucceeds() { return $this->assertTrue(isset($this->pata[$this->key])); } function testIssetWithWrongKeyFails() { return $this->assertFalse(isset($this->pata[$this->garbage])); } function testGetWithPathAsKey() { return $this->assertEquals($this->path, $this->strval($this->pata[$this->key])); } private function strval($v) { if (is_object($v)) { return $v->__toString(); } else { return strval($v); } } } class pata_WinTest extends pata_MultipleSegmentTest { function separator() { return '\\'; } } class pata_POSIXTest extends pata_MultipleSegmentTest { function separator() { return '/'; } } class pata_tests extends Tence_TestSuite { function __construct() { $this ->add(new pata_SingleSegmentTest) ->add(new pata_WinTest) ->add(new pata_POSIXTest) ; } } ?> -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 |