Converting string representation of a directory to multi-dimensional array

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>\&...


Go Back   Usenet Forums > PHP Programming Forums > PHP General

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-05-2007
Matt Carlson
 
Posts: n/a
Default Converting string representation of a directory to multi-dimensional array

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);

?>




Reply With Quote
  #2 (permalink)  
Old 02-05-2007
Jochem Maas
 
Posts: n/a
Default Re: [PHP] Converting string representation of a directory to multi-dimensionalarray

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);
Reply With Quote
  #3 (permalink)  
Old 02-06-2007
Richard Lynch
 
Posts: n/a
Default Re: [PHP] Converting string representation of a directory tomulti-dimensional array

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?
Reply With Quote
  #4 (permalink)  
Old 02-06-2007
Jochem Maas
 
Posts: n/a
Default Re: [PHP] Converting string representation of a directory tomulti-dimensional array

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.

> }
> }
>

Reply With Quote
  #5 (permalink)  
Old 02-06-2007
Roman Neuhauser
 
Posts: n/a
Default Re: [PHP] Converting string representation of a directory to multi-dimensional array

# 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
Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 08:54 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0