php - Group multidimensional array

42

Given the following array:

var dates = ['2012-10-01', '2012-10-02', '2012-10-03', '2011-01-01', '2011-01-02', '2011-06-03', '2010-09-01', '2010-09-02', '2010-08-22' ];

I need it grouped by year then month then day so that my final result is something like this:

Array (
   "2012" => 
       Array ( "10" => Array ["01", "02", "03"] )

   "2011" =>
       Array ( "01" => Array ["01", "02"] )
       Array ( "06" => Array ["03"] )

   "2010" =>
       Array ( "09" => Array ["01", "02"] )
       Array ( "08" => Array ["22"] )
)

In the end I will auto populate a MM/DD/YYYY drop downs. So if a user selects year 2012 the following month drop down value is only 10 followed by the day drop down which would only have 01, 02, 03. If they select 2011 the following month drop down would only say 01, 06. If they select 01 then the following days would only be 01 or 02.

Hope that didnt confuse anyone and the question is clear. Multidimensional arrays are the worst I know.

Ideally Id like to do this in Javascript but PHP is ok too. One array in, one array out.

472

Answer

Solution:

This would do it:

$dates = array('2012-10-01', '2012-10-02', '2012-10-03', '2011-01-01', '2011-01-02', '2011-06-03', '2010-09-01', '2010-09-02', '2010-08-22');

$out = array();

foreach($dates as $date)
{
    $parts = explode('-',$date);

    if (!isset( $out[$parts[0]] ))
        $out[$parts[0]] = array();

    if (!isset( $out[$parts[0]] [$parts[1]] ))
        $out[$parts[0]] [$parts[1]] = array();

    if (!in_array($parts[2], $out[$parts[0]] [$parts[1]] )) 
        $out[$parts[0]] [$parts[1]] [] = $parts[2];
}

var_dump($out);

Output:

array
  2012 => 
    array
      10 => 
        array
          0 => string '01' (length=2)
          1 => string '02' (length=2)
          2 => string '03' (length=2)
  2011 => 
    array
      '01' => 
        array
          0 => string '01' (length=2)
          1 => string '02' (length=2)
      '06' => 
        array
          0 => string '03' (length=2)
  2010 => 
    array
      '09' => 
        array
          0 => string '01' (length=2)
          1 => string '02' (length=2)
      '08' => 
        array
          0 => string '22' (length=2)
193

Answer

Solution:

Use Underscore.js

_.map(list, iterator, [context]) Alias: collect
Produces a new array of values by mapping each value in list through a transformation function (iterator). If the native map method exists, it will be used instead. If list is a JavaScript object, iterator's arguments will be (value, key, list).

_.reduce(list, iterator, memo, [context]) Aliases: inject, foldl
Also known as inject and foldl, reduce boils down a list of values into a single value. Memo is the initial state of the reduction, and each successive step of it should be returned by iterator.

Example:

var dates = ['2012-10-01', '2012-10-02', '2012-10-03', '2011-01-01', '2011-01-02', '2011-06-03', '2010-09-01', '2010-09-02', '2010-08-22' ];
_.chain(dates)
    .map(function(date){ return date.split('-'); })
    .reduce(function(memo, num){ 
        if(!memo[num[0]]){ memo[num[0]] = {}; }
        if(!memo[num[0]][num[1]]){ memo[num[0]][num[1]] = []; }
        memo[num[0]][num[1]].push(num[2]);
        return memo;
    }, {})
    .tap(function(curVal){ alert(JSON.stringify(curVal)); })

//Produces
​{
   "2010":{
      "09":[
         "01",
         "02"
      ],
      "08":[
         "22"
      ]
   },
   "2011":{
      "01":[
         "01",
         "02"
      ],
      "06":[
         "03"
      ]
   },
   "2012":{
      "10":[
         "01",
         "02",
         "03"
      ]
   }
}
873

Answer

Solution:

First, you parse all the date strings out in to their separate parts. Then, you iterate through those parts, and put them in to the appropriate arrays.

(A very general answer for a very general question.)

People are also looking for solutions to the problem: php - pagination bold on page click

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.