Reputation: 2333
So I have a file that has strings of file paths that look like this..
./CatDV/S1/SFX/steam/6004_90_04 LargeHeadlightSm.wav
./CatDV/S1/SFX/steam/AirHissPressureRe HIT032001.wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit(1).wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit.wav
./CatDV/S1/SFX/steam/6004_94_02 LargeHeavyGlassS.wav
./CatDV/S1/SFX/steam/Impact_Glass_Smash.wav
./CatDV/S1/SFX/steam/AirReleaseHeavyAi HIT030701.wav
./CatDV/S1/SFX/steam/SDR02_15SCIF RhythmicRever.wav
./CatDV/S1/SFX/steam/VAL02_08CRSH GlassBreaking.wav
./CatDV/S1/SFX/steam/AirReleaseLargeAi HIT030601.wav
./CatDV/S1/SFX/steam/SDR02_14SCIF Rhythmic3Beat.wav
./CatDV/S1/SFX/steam/6004_94_01 LargeGlassSmash.wav
I want to split all of these to an ul li list.so
> CatDV
> S1
> SFX
> steam
> filename.extension
And so forth...
This is the array that i'm working with. And i got this to output with the function below.
array(1) {
[""]=>
array(1) {
["CatDV"]=>
array(1) {
["S1"]=>
array(1) {
["SFX"]=>
array(1) {
["steam"]=>
array(12) {
["6004_90_04 LargeHeadlightSm.wav"]=>
string(52) "./CatDV/S1/SFX/steam/6004_90_04 LargeHeadlightSm.wav"
["AirHissPressureRe HIT032001.wav"]=>
string(52) "./CatDV/S1/SFX/steam/AirHissPressureRe HIT032001.wav"
["Impact_Metal_Bullet_Hit(1).wav"]=>
string(51) "./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit(1).wav"
["Impact_Metal_Bullet_Hit.wav"]=>
string(48) "./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit.wav"
["6004_94_02 LargeHeavyGlassS.wav"]=>
string(52) "./CatDV/S1/SFX/steam/6004_94_02 LargeHeavyGlassS.wav"
["Impact_Glass_Smash.wav"]=>
string(43) "./CatDV/S1/SFX/steam/Impact_Glass_Smash.wav"
["AirReleaseHeavyAi HIT030701.wav"]=>
string(52) "./CatDV/S1/SFX/steam/AirReleaseHeavyAi HIT030701.wav"
["SDR02_15SCIF RhythmicRever.wav"]=>
string(51) "./CatDV/S1/SFX/steam/SDR02_15SCIF RhythmicRever.wav"
["VAL02_08CRSH GlassBreaking.wav"]=>
string(51) "./CatDV/S1/SFX/steam/VAL02_08CRSH GlassBreaking.wav"
["AirReleaseLargeAi HIT030601.wav"]=>
string(52) "./CatDV/S1/SFX/steam/AirReleaseLargeAi HIT030601.wav"
["SDR02_14SCIF Rhythmic3Beat.wav"]=>
string(51) "./CatDV/S1/SFX/steam/SDR02_14SCIF Rhythmic3Beat.wav"
["6004_94_01 LargeGlassSmash.wav"]=>
string(51) "./CatDV/S1/SFX/steam/6004_94_01 LargeGlassSmash.wav"
}
}
}
}
}
}
Now what I'm getting stuck in converting this into an ul li list that i can output into my html and style it.
function arch_list($output) {
// //Conditional for Archives Page
$data = file(get_template_directory_uri() . '/js/angular/data/list_test.txt', FILE_IGNORE_NEW_LINES);
$path = array('data' => $data);
$output = array();
foreach ($path['data'] as $d) {
$out = preg_split('/(\.)*\//', $d);
$outArr = $d;
for ($i = count($out) - 1; $i >= 0; $i--) {
$outArr = array($out[$i] => $outArr);
}
// return $outArr;
$output = array_merge_recursive($output, $outArr);
}
return $output;
}
Any help is appreciated! Thanks.
Upvotes: 1
Views: 477
Reputation: 165201
I have refactored the god-awful code in @hakre's answer to be slightly less god-aweful. It's using the same aglorithm:
$file = './CatDV/S1/SFX/steam/6004_90_04 LargeHeadlightSm.wav
./CatDV/S1/SFX/steam/AirHissPressureRe HIT032001.wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit(1).wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit.wav
./CatDV/S1/SFX/steam/6004_94_02 LargeHeavyGlassS.wav
./CatDV/S1/SFX/steam/Impact_Glass_Smash.wav
./CatDV/S1/SFX/steam/AirReleaseHeavyAi HIT030701.wav
./CatDV/S1/SFX/steam/SDR02_15SCIF RhythmicRever.wav
./CatDV/S1/SFX/steam/VAL02_08CRSH GlassBreaking.wav
./CatDV/S1/SFX/steam/AirReleaseLargeAi HIT030601.wav
./CatDV/S1/SFX/steam/SDR02_14SCIF Rhythmic3Beat.wav
./CatDV/S1/SFX/steam/6004_94_01 LargeGlassSmash.wav';
These are internal functions, which you don't need to directly call.
function splitIntoPaths($string) {
$paths = array();
foreach (explode("\n", $string) as $line) {
$node = &$paths;
foreach (explode("/", $line) as $segment) {
if (!isset($node[$segment])) {
$node[$segment] = array();
}
$node = &$node[$segment];
}
$node = $line;
}
return $paths;
}
function createListFromArray(array $array) {
$return = "<ul>";
foreach ($array as $key => $value) {
$return .= "<li>" . $key;
if (is_array($value)) {
$return .= createListFromArray($value);
}
$return .= "</li>";
}
return $return . "</ul>";
}
This is the function that does the work for you, returning you a string.
function createTree($string) {
$paths = splitIntoPaths($string);
return createListFromArray($paths);
}
Usage:
$tree = createTree($file);
Upvotes: 6
Reputation: 1410
I'm looking at @hakre 's. It puts the lowest level key=>value as 2 <li>'s which I don't think is what is wanted. My solution (given that one has the multi-dimensional array):
$arrayvar = array("blank?"=>
array("CatDV"=>
array("S1"=>
array("SFX"=>
array("steam"=>
array("6004_90_04 LargeHeadlightSm.wav"=>
"./CatDV/S1/SFX/steam/6004_90_04 LargeHeadlightSm.wav",
"AirHissPressureRe HIT032001.wav"=>
"./CatDV/S1/SFX/steam/AirHissPressureRe HIT032001.wav"))))));
makeul($arrayvar);
function makeul($avar) { // make ul
if (!is_array($avar)) exit("Err: not an array");
echo("<ul>");
reset($avar); while(true) { // loop through array
$key = key($avar);
if (is_null($key)) break; // if NULL, end of loop
$val = $avar[$key];
if (is_scalar($val)) zecho("<li>$key=>$val</li> ");
else { zecho("<li>$key"); makeul($val); zecho("</li>"); } // recurse
next($avar); }
zecho("</ul>");
}
function zecho($param) { // echo with br & \n
echo $param, "<br />\n";
}
Edit (for hakre): I learned a lot from your code, thank you, but isn't it unnecessarily obscure?
Wouldn't the following be as good and more clear?
$tree = ..
makeul($tree, '');
function makeul($val, $key) {
if ($key <> "") echo "<li>$key\n";
if (is_array($val)) {
echo("<ul>"); array_walk($val, 'makeul'); echo("</ul>\n"); }
else {
echo("=>$val<br />\n"); }
if ($key <> "") echo "</li>";
}
Upvotes: 0
Reputation: 1738
Try this
<?php
$fileToOpen="/js/angular/data/list_test.txt";
function arch_list($fileToOpen) {
if(file_exists($fileToOpen)){
$file=fopen($fileToOpen,"r");
while($line = fgets($file)){
//We have a line of the file,split it up
$directories=explode("/",$line);
//Remove the period, it will be the first element in the array
$directories=array_shift($directories);
//Add this set of directories to a parent array
$allDirectories[]=$directories;
}
fclose($fileToOpen);
}//End of opening file
//We now have a multidimensional array,
//An array holding arrays with each set of directories.
if(!empty($allDirectories)){
foreach($allDirectories as $directory){
$fullString.="<ul class='your-class'>";
foreach($directory as $pathway){
//We have each single item in a directory path
$fullString.="<li>".$pathway."</li>";
}
$fullString.="</ul>";
}
}
return $fullString;
}
echo arch_list($fileToOpen);
?>
Upvotes: 0
Reputation: 197795
As you don't know the depth of your tree, you can make use of recursive function calls to display the ul/li tree. This actually works like in this yesterdays question, however, you have different decision points here:
$file = './CatDV/S1/SFX/steam/6004_90_04 LargeHeadlightSm.wav
./CatDV/S1/SFX/steam/AirHissPressureRe HIT032001.wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit(1).wav
./CatDV/S1/SFX/steam/Impact_Metal_Bullet_Hit.wav
./CatDV/S1/SFX/steam/6004_94_02 LargeHeavyGlassS.wav
./CatDV/S1/SFX/steam/Impact_Glass_Smash.wav
./CatDV/S1/SFX/steam/AirReleaseHeavyAi HIT030701.wav
./CatDV/S1/SFX/steam/SDR02_15SCIF RhythmicRever.wav
./CatDV/S1/SFX/steam/VAL02_08CRSH GlassBreaking.wav
./CatDV/S1/SFX/steam/AirReleaseLargeAi HIT030601.wav
./CatDV/S1/SFX/steam/SDR02_14SCIF Rhythmic3Beat.wav
./CatDV/S1/SFX/steam/6004_94_01 LargeGlassSmash.wav';
$tree = [];
foreach (explode("\n", $file) as $line) {
$node = &$tree;
foreach (explode('/', $line) as $segment) {
$node = &$node[$segment];
}
$node = $line;
unset($node);
}
call_user_func(function ($array) {
$ul = function ($array) use (&$ul) {
echo '<ul>', !array_walk($array, function ($child, $key) use ($ul) {
echo '<li>', $key, is_array($child) ? $ul($child) : ''
, '</li>';
}, $array), '</ul>';
};
$ul($array);
}, $tree);
Take note that this self-containing example code (Demo) also contains a different way to build the $tree
array comparable but a little different to your way (the main difference is that I didn't use array_merge_recursive()
but instead merged on my own by using references while traversing the $tree
array).
For the recursion it's really straight forward once you've understood how recursive function calls work: Solve the problem for one list and wrap the solution into a function. Then insert a new list if that lists entries have children. Use the same function for that.
Output (beautified):
<ul>
<li>.
<ul>
<li>CatDV
<ul>
<li>S1
<ul>
<li>SFX
<ul>
<li>steam
<ul>
<li>6004_90_04 LargeHeadlightSm.wav</li>
<li>AirHissPressureRe HIT032001.wav</li>
<li>Impact_Metal_Bullet_Hit(1).wav</li>
<li>Impact_Metal_Bullet_Hit.wav</li>
<li>6004_94_02 LargeHeavyGlassS.wav</li>
<li>Impact_Glass_Smash.wav</li>
<li>AirReleaseHeavyAi HIT030701.wav</li>
<li>SDR02_15SCIF RhythmicRever.wav</li>
<li>VAL02_08CRSH GlassBreaking.wav</li>
<li>AirReleaseLargeAi HIT030601.wav</li>
<li>SDR02_14SCIF Rhythmic3Beat.wav</li>
<li>6004_94_01 LargeGlassSmash.wav</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Upvotes: 3