Jump to content

How do I count the sub-values under the 'first' key in a multidimensional array?


Theriex

Recommended Posts

I have this date/time multidimensional array set up and I want to count how many "times" are listed under the key "2012" for example.  The result should be 4 as there are four times (16:11:45, 12:14:16, 11:12:43 and 19:27:11) under 2012.  I've tried a bunch of foreach loops which didn't get me far.  I tried using array_count_values which didn't work either.

 

I'm really stuck on this :(

 

$arr = array(
	"2012" => array(
		"January" => array(
			"10" => array(
				"16:11:45"
			),
			"24" => array(
				"12:14:16"
			)
		),
		"February" => array(
			"14" => array(
				"11:12:43"
			),
			"17" => array(
				"19:27:11"
			)
		)
	),
	"2011" => array(
		"May" => array(
			"2" => array(
				"12:13:14"
			),
			"29" => array(
				"01:02:56"
			)
		),
		"August" => array(
			"1" => array(
				"08:45:01"
			),
			"9" => array(
				"23:11:24"
			)
		)
	)
);

Link to comment
Share on other sites

you nest foreach loops with different counters to reference the index as $myArray[$i][$k]. 

$i = 0;
$k=0;
foreach($myArray as $row) //or as $key0 => $val0 depending on what you want to do
{
     foreach($myArray[$i] as $row1)//or $key1 => $val1
    {
// you can keep delving down if you need to
    }
}

just throw in your count() wherever appropriate for the subarray you need to get a count of its elements. 

Link to comment
Share on other sites

The array is generated from a timestamp in a database.  I'm creating a personal page with a blog, the counting of the date/time array is for the archive.

 

The output would look like this for example:

 

> 2012 (4)

  >  January (2)

      > Some Title

      > Some Title

  > April (1)

      > Some Title

  > December (1)

      > Some Title

 

The count gives me the count for all entries in 2012 and all months individually.  I'm also using the "day" and "time" in the array so I can go to that specific entry, which I suppose I could just use the title of the entry.

 

Does that make sense?  I know i'm probably making this way more complex than needed :)

Link to comment
Share on other sites

Think of a multidimentional array as an array inside an array key.  The important part to remember here is that each KEY in your "top level" elements each contain an array instead of a single value. That means you have multiple arrays on the 2nd level.  Each KEY in the 2nd level can have an array in it, so again instead of a "3rd level" which can be counted in total, each KEY in the 2nd level has an array which can be counted. 

( I hope this layout works when you view it)

                                          topLevelElement0                                                                            topLevelElement1

                      2ndLevel Element 0        2nd Level Elem 1                                            2ndLevelElem 0          2ndLevelElem 1

3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1

 

And so on.  Remember that each level can have a different number of elements than its siblings although in the example I made each element have 2 sub elements.

 

When you nest the foreach in my example and run count(), you'll get 2 in the above example, not 2, 4, or 8 respectively.

You access a subelement by accessing the parent element and stepping through it's index, just as you would a single-dimensional array.

To access the keys and values in a single-dimensional array you pass the array through a foreach

foreach($myArray as $key => $val)
{
    echo $key ,"&".$val."<br/>";
}

will output

topLevelElement0 & array

topLevelElement1 & array

 

Now, if we nest a 2nd foreach inside the first and do the same but change the variable names so we don't conflict:

foreach($myArray as $key0 => $val0)
{
    echo $key0 ,"&".$val0."<br/>";
    foreach($myArray as $key1 => $val)
    {
         echo $key1 ,"&".$val1."<br/>";
    }
}

 

will output

topLevelElement0 & array                                                                           

2ndLevel Element 0 & array

2nd Level Elem 1 & array

topLevelElement1 & array

2ndLevelElem 0 & array

2ndLevelElem 1 & array

 

Does that help?

 

 

 

Link to comment
Share on other sites

Sorry, still having problems.  I tried adapting what you have to my code but still no love.

 

Taking your example with the array:

 

                                            topLevelElement0                                                                            topLevelElement1

                      2ndLevel Element 0        2nd Level Elem 1                                            2ndLevelElem 0          2ndLevelElem 1

3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1    3rdLevelElem0    3rdLevelElem1

 

I still don't understand how to count all of the 3rdLevelElements under topLevelElement0.

 

All i've been able to do is count ALL 3rdLevelElements together under both topLevelElement0 and topLevelElement1, which gives me 8 instead of the 4 under topLevelElement0.

Link to comment
Share on other sites

Noticed an error in my code--I forgot to put in the individual counters; it's corrected in this example

 

Just noticed that you're trying to get, for instance, a total count of entries for the year, so you'll need to count the length of .  Given the array layout you made in the last post, you can either just increase a total counter (probably easier) or set counters at each level and use that counter to access the value of specific elements.  Doing something like

$totalCounter = 0;
$i =0;
foreach($myArray as $key0 => $val0)
{
     $k = 0;   
    echo $key0 ,"&".$val0."<br/>";   
    foreach($myArray[$i] as $key1 => $val1)
    {        
         $l = 0;
          echo $key1 ,"&".$val1."<br/>"; 
          foreach($myArray[$i][$k] as $key2 => $val2)
          {
             $totalCounter++;
          }  
          $k++;
    }
    $i++;
}

by the time you get done, $totalCounter should be the total number of articles

 

 

Link to comment
Share on other sites

I was getting a bunch of convert array to string errors from that, but it was due to the echo or $val0, $val1... etc.  I commented those out and let the counter run, but I still end up with all 8 from both years :(

 

I moved the totalCounter back by one in the nested loops and I got 4, but which 4 is it counting? So I added echo $key0 , $key1;  This showed 2012January2012February2011May2011August, which as I suspected is counting the four months combined from both years.

 

This is actually the point where I got stuck in my code :( 

Link to comment
Share on other sites

Because that's a very convoluted way to represent dates and times.

 

Assuming you are getting the date/time ($row['date']) and title ($row['title']) in the rows from your query and the rows are in the order that you want the result to be in, you can directly and simply loop over the data and produce the desired output  -

 

// execute your query here to get the data you want in the order that you want it....

$last_year = null;
$last_month = null;
$output = '<ul>';

while($row = mysql_fetch_assoc($result)){
list($year,$month,,,,) = sscanf($row['date'],"%d-%d-%d %d:%d:%d"); // extract just the year and month

if($last_month != $month){
	// month changed or is the first one
	if($last_month != null){
		// not the first one, close out (produce) the previous month section
		$month_name = date("F",mktime(0, 0, 0, $last_month));
		$year_data .= "<li>$month_name ($month_count)</li><ul>$month_data</ul>";
	}
	$month_count = 0;
	$month_data = '';
	$last_month = $month;
}

if($last_year != $year){
	// year changed or is the first one
	if($last_year != null){
		// not the first one, close out (produce) the previous year section
		$output .= "<li>$last_year ($year_count)</li><ul>$year_data</ul>";
	}
	$year_count = 0;
	$year_data = '';
	$last_year = $year;
}

// each piece of data under the current month
$month_data .= "<li>{$row['title']}</li>";
$month_count++;
$year_count++;
}
// close out the last section
$month_name = date("F",mktime(0, 0, 0, $last_month));
$year_data .= "<li>$month_name ($month_count)</li><ul>$month_data</ul>";

$output .= "<li>$last_year ($year_count)</li><ul>$year_data</ul>";
$output .= '</ul>';

echo $output;

Link to comment
Share on other sites

The field i'm grabbing from the database is a timestamp, so its in the format of YYYY-MM-DD XX:XX:XX. <- Ignore this, i'm getting tired lol.

 

I need to parse all of that (which i've already done) and get the specific day and time in the array as well. I will be using the time as an identifer for the title's listed in the archive, that way when they are clicked on, I can easily do a search in the database for that entry and display it.

 

Edit: I looked at that again, and it might actually work for me, i'm gonna play around with it some and see.

Link to comment
Share on other sites

I will be using the time as an identifer for the title's listed in the archive, that way when they are clicked on, I can easily do a search in the database for that entry and display it.

 

Just using a time is ambiguous. You should be using the id (auto-increment key) in links to reference any particular entry.

Link to comment
Share on other sites

Here's what works to get the count of total articles (you can adapt it as necesary to get other elements...)

My example wasn't working because in the jump from theoretical example to your specific array I failed to account for my example using index base, whereas your real example is associative.  The code below works with associative arrays: (and here you won't need the $i or $k counters...they're just left in from the previous version and should come out.  )

 

<?php

 

$arr = array(

"2012" => array(

        "January" => array(

                    "10" => array("16:11:45"),

                                    "24" => array("12:14:16")

                                    ),

                    "February" => array(

                    "14" => array("11:12:43"),

                      "17" => array("19:27:11")

                                    )

        ),

        "2011" => array(

        "May" => array(

                    "2" => array("12:13:14"),

                                    "29" => array("01:02:56")

                    ),

                    "August" => array(

                    "1" => array("08:45:01"),

                      "9" => array("23:11:24")

                          )

                      )

);

 

$totalCounter = 0;

$i =2012;

foreach($arr as $key0 => $val0)

{

    $k = 0;     

    echo $key0."<br/>";

    foreach($arr[$key0] as $key1 => $val1)

        {               

          $l = 0;         

          echo $key1."<br/>";         

          foreach($arr[$key0][$key1] as $key2 => $val2)         

          {           

          $totalCounter++;       

          }           

    $k++;   

  }   

$i = $i-1;

}

echo "<br/>TotalCount is: ".$totalCounter;

?>

[code=php:0]

 

here's the script in action, counting 8 total articles:

 

http://betaportal.ankertechnicalservices.com/arraytest.php

Link to comment
Share on other sites

This code specifically does what you asked way back in the beginning:  Counts the number of times in each year and reports 4.  (example at same url as above post)

$totalCounter = 0;
foreach($arr as $key0 => $val0)
{
$timesCount = 0;       
     echo $key0."<br/>";
     foreach($arr[$key0] as $key1 => $val1)
         {                       
          echo $key1."<br/>";           
          foreach($arr[$key0][$key1] as $key2 => $val2)          
          {             
          	$totalCounter++; 
		$timesCount++;
          }              
   		}    
echo "<br/>timesCount for $key0 is: $timesCount<br/>";
}
echo "<br/>TotalCount is: ".$totalCounter;

 

Link to comment
Share on other sites

Thanks to both of you!  It's very close to what I need now.  I think i'm going to go with PFMaBiSmAd's example as it gets rid of the ridiculous arrays I had originally intended to go with.

 

Edit: Finally after some tinkering, it is working correctly.  Thank you to both of you for your help, it is much appreciated!

 

 

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

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.