Jump to content

Filling Both The Key And Value Of An Array With Foreach.


therschbach
 Share

Recommended Posts

As the topic says, I'm trying to fill both the key and value of an array, where the value is another array with an appended value to the existing array. In the end, I want the array to look like this....$main_array($year => $months_in_year($months)Is this possible to do in one statement via nested loops? Here is my entire php code.

	<?php	// View the archives directory and create an array of the file names	$handle = opendir('./archives');	for ($i=0; (false !== ($file = readdir($handle))); $i++) {		if ($file != "." && $file != "..") {			$files_array[$i] = $file;		}	}	closedir($handle);	//Create an array that contains one value for each year that archive exists (last 2 digits of filename)	$year_menu_array = array();	foreach ($files_array as $filename) {		$year = substr($filename, -2);		if (in_array($year, $year_menu_array) === false) {			$year_menu_array[] = $year;		}	}	sort($year_menu_array);					//Create and fill the year menu, this works!	echo ("<div id='archivesyearmenu'>");	echo ("<table id='archivesyeartable'>");	foreach ($year_menu_array as $value){		echo ("<tr><td id=20" . $value);		echo ( " onMouseOver='menuButtonOn(this);' onMouseOut='menuButtonOff(this);'>");		echo ( "20" . "$value" . "</td></tr>");	}	echo ("</table>");	echo ("</div>");		//Create arrays for each year that contain only months available	foreach ($year_menu_array as $year) {		echo ("Inside first foreach loop.  Year is $year.  <br>");				foreach ($files_array as $filename) {			echo ("Inside 2nd foreach loop.  Filename is $filename. <br>");			if (substr($filename, -2) == $year) {				$month = substr($filename, 0, -2);				$month_array = array($year => $each_years_months[$month]);				echo ("Inside if statement, month is $month. <br>");				print_r ($month_array);				echo ("<br><br>");			}		}	}		?>

Everything works up until the bottom where I define the array $month_array. The array gets set, but the value never gets set and each time it loops through, it just overwrites the previous key without creating any new ones, even if the value $year is different. What am I doing wrong?

Link to comment
Share on other sites

For one, every time you create $month_array you're creating a new array, you're not adding to an existing array.
I figured that out because it just replaced the key each time with a new key.I would think that it should be set like this....$month_array [$year => $each_years_months[$month]] = But I don't know what it should be equal too because there are two variables that need to be set at the same time. That extends beyond the limits of my 48 hour php knowledge and I didn't see it in the manual. :)EDIT: I just realized that $year is already being set by the foreach loop so I only need to set the $each_years_month value. So....$month_array [$year => $each_years_months[]] = $month;I'm not at home right now so I can't test this, but should this work?
Link to comment
Share on other sites

No, that won't work. It's just confusing enough that I'm not quite sure what you're trying to do. You may be looking for one of these:$month_array[$year][$each_years_months] = $month;$month_array[$year][$each_years_months][] = $month;

Link to comment
Share on other sites

lol, it's confusing the heck out of me too.$month_array is an array.$month_array has keys of $year....so "05" "06" "07", etc.The value for each key, is another array, $each_years_months[]. This array doesn't need defined keys, and the values are filled with $month.So an example entry for $month_array should be...$month_array("07" => $each_years_months( 1 => april)) or...$month_ array("05" => $each_years_months(0 => february))The entire code looks at the archive list of files that I have that are named april07, february05, etc.... and creates a drop-down menu table that contains each year that exists. I've got this part to work. From there, I want to create a new drop-down menu table for each year that exists that contains the months that exist in that year...which will be $each_years_months. Follow?I'm fairly confident in the logic, because if I use the original code posted above that actually runs with no errors, the loops cycle through each year and spit out the months that are available for each year. It just won't populate the arrays (multiple arrays, one for each year) with the $months, and it overwrites the key to whatever current $year it is looping through...and when it is done, I only have $month_array("07"=>).Given the files that are located in my archives folder, I want the array to end up like this when it's done...$month_array ("05" => $each_years_months ( august, september, october, november, december) "06" => $each_years_months ( january, february, march, april, may, june, july, august, september, october, november, december) "07" => $each_years_months ( january, february, march, april, may, june, july, august, september, october, november, december) "08" => $each_years_months ( january, february, march, april, may, june, july, august, october, november, december) )instead, it ends up like this...$month_array ("07" => )I hope this makes sense.

Link to comment
Share on other sites

Ok, I'm getting closer.... :) I replaced $month_array = array($year => $each_years_months[$month]);with$month_array[$year] = $each_years_months;$each_years_months[] = $month;This is populating the arrays, although not correctly. It seems to be tagging on the contents of the current years array to the next years array.

Link to comment
Share on other sites

Now I have another problem that is directly related to this script, but I'm not sure if I should make a new thread for it. I'll just post it here and hope you see it.I'm trying to echo out the contents of the nested array by key, but I'm not sure how to address it in the foreach loop.

	foreach ($month_array as $yearvalue) {		echo ("<div id='{$year}menu'>");		echo ("<table class='{$year}table'>");		foreach ($month_array as $monthvalue){			echo ("<tr><td id=" . $month . $year);			echo ( " onMouseOver='menuButtonOn(this);' onMouseOut='menuButtonOff(this);'>");			echo ( "'$month</td></tr>");		}		echo ("</table>");		echo ("</div>");	}

So for each $yearvalue, I want a new table. For each $monthvalue I want a new <td> entry within that corresponding table.

Link to comment
Share on other sites

Yes, I think my problem is that I don't know how to "access" the nested arrays once I'm out of the original foreach loop that creates the $month_array.$month_array[$year][] = $month;So if I want to just echo out the values of each nested array one by one... what's the correct syntax using a foreach loop? I think that's where I'm hung up.

Link to comment
Share on other sites

This will print all values of nested arrays:

$array = array(  array(	'one',	'two',	'three'  ),  array(	'four',	'five',	'six'  ));foreach ($array as $key1 => $subarray){  foreach ($subarray as $key2 => $value)  {	echo 'array[' . $key1 . '][' . $key2 . '] = ' . $value . '<br>';  }}

Link to comment
Share on other sites

Ok, now the problem is that the subarray doesn't have a name, or at least I don't think it does.$month_array[$year][] = $month;$array = $month_array$key1 = $year$subarray = ??Or is $year the $subarray? I'll tell ya, thinking about loops for a few hours really melts my brain.

Link to comment
Share on other sites

Alright, everything is working! Well, one minor detail remains.I now have arrays containing months. What would be the best way to sort the months chronologically? The only way I can think of is to make an array that has all the months in order and compare it with the arrays the script is building. Would this be the only way?

Link to comment
Share on other sites

It's the same as sort except you use your own comparison function. The regular sort function will sort alphabetically, if you want it to sort on some arbitrary criteria (like month order), then you use usort. The comparison function takes 2 arguments ($a and $b, for example), and it needs to return -1 if $a comes before $b, +1 if $b comes before $a, or 0 if they are equal. So your comparison function will take 2 month names and return a value less than or greater than 0 to say which one goes first. It would probably be easiest to convert both month names to their corresponding numbers, then subtract one from the other. The result will be either less than or greater than 0 (it doesn't need to be -1 or +1, just negative or positive).

Link to comment
Share on other sites

This is the example from the manual.

function cmp($a, $b){	if ($a == $b) {		return 0;	}	return ($a < $b) ? -1 : 1;}$a = array(3, 2, 5, 6, 1);usort($a, "cmp");

What are $a and $b? I'm going to assume that the array $a is not the same thing as the $a in the function. If I renamed the array to $array, the function would still be cmp($a, $:), right? If so, I don't know why they named it $a as that is very confusing.

Link to comment
Share on other sites

They could call them anything they want, $a and $b are just generic. $a and $b are the two items being compared, so they will each be an element in the array. PHP will iterate through the array and send every pair of elements to the comparison function to figure out which one should go first. The elements it sends are the two arguments to the comparison function, but you can name them anything you want.

Link to comment
Share on other sites

Well, I found it was easier for me to just compare the list of months that I have with a list of all months and if the month was in the array, then add it to a new array which I used to temporarily hold the data until each year was done, when I dumped each years menu into a table, one by one. And I can hardly believe it, but it works!! Here's the code in it's entirety with plenty of comments.

<?php// View the archives directory and create an array ($files_array) of the file names$handle = opendir('./archives');for ($i=0; (false !== ($file = readdir($handle))); $i++) {	if ($file != "." && $file != "..") {		$files_array[$i] = $file;	}}closedir($handle);	//Create an array ($year_menu_array) that contains one value for each year (last 2 digits)//Then sort the years numerically	$year_menu_array = array();foreach ($files_array as $filename) {	$year = substr($filename, -2);	if (in_array($year, $year_menu_array) === false) {		$year_menu_array[] = $year;	}}sort($year_menu_array);				//Create and fill the year menuecho ("<div id='archivesyearmenu'>\n");echo ("<table id='archivesyeartable'>\n");foreach ($year_menu_array as $value){	echo ("<tr><td id='$value'");	echo ( " onMouseOver='menuButtonOn(this), reveal(\"$value\");'  onMouseOut='menuButtonOff(this), hide(\"$value\");'>");	echo ( "20" . "$value" . "</td></tr>\n");	}	echo ("</table>");	echo ("</div>\n");		//Create nested arrays within an array ($month_array) for each year that contain only months available$month_array = array();foreach ($year_menu_array as $year) {	foreach ($files_array as $filename) {	//Get last 2 digits of filename which is the year		$file_year = substr($filename, -2);		if ($file_year == $year) {				$month = substr($filename, 0, -2);			$month_array[$year][] = $month;		}	}}	//Create, sort, and fill the month menus, one for each year//$orderedMonthList is used to compare the available month list to for sorting by month	$month_array_ordered = array();$orderedMonthList = array(january, february, march, april, may, june, july, august, september, october, november, december);	//For each nested array in month_arrayforeach ($month_array as $yearkey => $year) {	//Compare the values to all months	foreach ($orderedMonthList as $key => $month) {		if (in_array($month, $year)) {			$sorted_months[$key] = $month;		}		//If it is the last month (December), create the info for the div and table for the current year menu		if ($key == "11") {			echo ('<div style="visibility:hidden" id="');			echo $yearkey;			echo ('menu" ');			echo ('class="monthMenu">');			echo ("\n");			echo ('<table class="monthTable">');			echo ("\n");			//Create the info for each table data entry			foreach ($sorted_months as $monthkey => $month){				echo ("<tr><td id=\"" . $monthkey . $yearkey);	echo ( "\" onMouseOver='menuButtonOn(this);' onMouseOut='menuButtonOff(this);'>");	$month = ucfirst($month);	echo ( "$month</td></tr>\n\n");			}			echo ("</table>");			echo ("</div>\n");			//Reset the $sorted_months array for the next foreach loop			unset($sorted_months);		}	}}?>

Thank you very very much guy! If I ever see you online, I'll try not to stab you in the back. :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...