Jump to content
Sandy_85

Populate array with recursive function

Recommended Posts

Posted (edited)

Hey there

I just started out with PHP so it might be a trivial problem. I want to populate an array with values by a recursive function but i don't get it the way i want it to have.

Target array (written in python syntax):

myArray = { 
	key : [
		[a1, a2, a3, a4], 
		[b1, b2, b3 ,b4]
	],
	key2 : [
		[c1, c2, c3, c4], 
		[d1, d2, d3, d4]
	]
}

So far i created a recursive function to collect all data i need for the array but i don't get the right syntax to achieve my target array.

What i have so far is following code (snippet):

function get_data($main_dir, $items=[], $myArray=[], $depth=0) {
	global $items;
	if ($myArray == NULL && depth == 0) {
		$myArray = array();
	}
	$depth++;
	$dirHandle = opendir($main_dir);
	
	while ($file = readdir($dirHandle)){
		if(is_dir($main_dir.$file) && $file != "." && $file != "..") {
			$new_dir = $main_dir.$file."/";
			$items = get_data($new_dir, $items, $myArray, $depth);
			$myArray = $items[1]
			$items = $items[0]
		}
		else {
			splitted_dir = preg_split("/\//", $main_dir);
			key = splitted_dir[2];
			file_information = read_out_file($main_dir.$file);
			information_1 = file_information[0];
			information_2 = file_information[1];

			myArray = array_merge($myArray, array($key, array($key, $information_1, $information_2, $main_dir, $file))
		}
	}
}

The array contains all informations i need but the structure of it is not useable.

Current output:

Array ( 
	[0] => key1 
	[1] => Array ( 
		[0] => key1 
		[1] => information_1 
		[2] => information_2 
		[3] => ./path/ 
		[4] => filename ) 
	[2] => key1 
	[3] => Array ( 
		[0] => key1 
		[1] => information_1
		[2] => information_2
		[3] => ./path/ 
		[4] => filename ) 
	[4] => key1 
	[5] => Array ( 
		[0] => key1 
		[1] => information_1
		[2] => information_2 
		[3] => ./path/ 
		[4] => filename ) 
	[6] => key2 
	[7] => Array ( 
		[0] => key2 
		[1] => information_1
		[2] => information_2
		[3] => ./path/ 
		[4] => filename ) 
	[8] => key2 
	[9] => Array ( 
		[0] => key2 
		[1] => information_1 
		[2] => information_2 
		[3] => ./path/ 
		[4] => filename ) 
) 1 

## IDK why this "1" at the end gets printed out... 

But what i want to get is this:

Array (
    [key1] => Array (
        Array (
            [0] => key1 
            [1] => information_1 
            [2] => information_2 
            [3] => ./path/ 
            [4] => filename ) 
        )
        Array (
            [0] => key1 
            [1] => information_1 
            [2] => information_2 
            [3] => ./path/ 
            [4] => filename ) 
        )
    )
    [key2] => Array (
        Array (
            [0] => key2 
            [1] => information_1 
            [2] => information_2 
            [3] => ./path/ 
            [4] => filename ) 
        )
        Array (
            [0] => key2 
            [1] => information_1 
            [2] => information_2 
            [3] => ./path/ 
            [4] => filename ) 
        )
    )
)

 

At the end i want to sort the output by alphabetic order of the keys which i should achieve with sort() i guess?

 

Greetings

Edited by Sandy_85

Share this post


Link to post
Share on other sites
Posted (edited)

edit:

the else statement in the function is a elseif statement which checks if $main_dir.$file is a file which matches the pattern of files i'm looking for

elseif (is_file($main_dir.$file) && other checks) {
	... populate array
}

 

Edited by Sandy_85

Share this post


Link to post
Share on other sites

The main thing when populating an array recursively is to pass the result array by reference. If you don't you are just passing a copy of the array to the next level and the copy is lost when the function returns.

Here's an example which scans a directory and adds the files to the results array.

If the file added is itself a directory then its subfiles are added to its subfiles array, and so on.

$results = [];
$path = "c:/inetpub/wwwroot/test/mytest";                            // start path

add_file($path, $results);

echo '<pre>', print_r($results, 1), '</pre>';                        // show results 


function add_file($fname, &$farray)                                  // NOTE : results array passed by reference
{
    $farray[$fname] = [];
    if (is_dir($fname)) {
        $files = glob("$fname/*");
        foreach ($files as $f) {
            add_file($f, $farray[$fname]);
        }
    }
}

Path structure

image.png.c0bcfe1eddf8203dc221ddb7f81ed249.png

Results

Array
(
    [c:/inetpub/wwwroot/test/mytest] => Array
        (
            [c:/inetpub/wwwroot/test/mytest/dir_1] => Array
                (
                    [c:/inetpub/wwwroot/test/mytest/dir_1/dir_1_A] => Array
                        (
                            [c:/inetpub/wwwroot/test/mytest/dir_1/dir_1_A/dir_1_B] => Array
                                (
                                    [c:/inetpub/wwwroot/test/mytest/dir_1/dir_1_A/dir_1_B/fileE.txt] => Array
                                        (
                                        )

                                )

                            [c:/inetpub/wwwroot/test/mytest/dir_1/dir_1_A/fileD.txt] => Array
                                (
                                )

                        )

                    [c:/inetpub/wwwroot/test/mytest/dir_1/fileC.txt] => Array
                        (
                        )

                )

            [c:/inetpub/wwwroot/test/mytest/dir_2] => Array
                (
                    [c:/inetpub/wwwroot/test/mytest/dir_2/fileF.txt] => Array
                        (
                        )

                )

            [c:/inetpub/wwwroot/test/mytest/fileA.txt] => Array
                (
                )

            [c:/inetpub/wwwroot/test/mytest/fileB.txt] => Array
                (
                )

        )

)

 

Share this post


Link to post
Share on other sites

Thx @gw1500se & @Barand

So far i get a step closer to my target array by populationg the array with this:

$sort_list = array_merge(
	$sort_list, 
	array(
		$key => array(
			$counter => array(
				$information_1, 
				$informatin_2, 
				$informatino_3, 
				$main_dir, 
				$file
			)
		)
	)
);

But the finished array is still not in the structure i want to have

Example Output:

array(7) { 
    [key1]=> array(1) { 
        [0]=> array(5) { 
            [0]=> string(6) info_1 
            [1]=> string(27) info_2 
            [2]=> info_3 
            [3]=> string(15) info_4 
            [4]=> string(36) info_5 
        } 
    } 
    [key2]=> array(1) { 
        [0]=> array(5) { 
            [0]=> string(6) info_1 
            [1]=> string(27) info_2 
            [2]=> info_3
            [3]=> string(15) _info_4 
            [4]=> string(36) info_5 
        } 
    } .....

For the first sight this output looks like i want it. but if i have identical keys this will not work anymore. It's just saving 1 entry for each key. Is the array_merge function the right way to go for this task?

 

@Barand depending on the keys i use but the problem in my case is similar to a recursive directory search but a little bit different. In my case i get data from different directories at different times so i can't add all the values or arrays of each directory in one go. But thanks for the &$variable hint . I'll rewrite my function and try it this way.

Share this post


Link to post
Share on other sites

Ok i got it now to work with:

if ($key != ""){
  $key = $key." ";
  if (!isset($sort_list[$key])){
  	$sort_list[$key] = [];
  }
  $sort_list[$key][sizeof($sort_list[$key])] = array($info_1, $info_2, strval($info_3), $path, $filename);
}

I used the $key = $key." " statement as my keys could be numbers (negative and positive) or strings. If i didn't do this any integer would be interpreted as array position instead of array key

I also rewrote the function

function get_all_data($filename, &$output, &$binary, &$sort_list, $depth=0) {
    if ($sort_list == NULL && $depth == 0) {
        $sort_list = array();
    }
    $depth++;
    if (is_dir($filename) && $filename != "." && $filename != "..") {
        $dir_content = glob("$filename/*");
        foreach ($dir_content as $f) {
            get_all_cards($f, $output, $binary, $sort_list, $depth);
        }
    }
    else {
        if (is_file($filename)){
			stuff ... 

 

Share this post


Link to post
Share on other sites

Op, tell us what the real problem is you are trying to solve with this rather than asking about your attempted solution to the problem. What is the high level overview of what you have going on?

Share this post


Link to post
Share on other sites
Posted (edited)

@benanamen The problem is solved already. I tried to sort a table by php. So depending on which column i wanted to sort the key values changed.

You can find the full code here (Github). It's the first function in this file and the page file list_all.php uses those function in get_cards.php

 

And i include my attempts as i just started to learn php this week and i might do a lot of mistakes or just don't know it better atm. This way more experienced users can give me some hints as they can identify the problem like @gw1500se and @Barand did

Edited by Sandy_85

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.