Kevin Davis
Kevin Davis

Reputation: 365

Sort a 2d array by one column then another column

I have the following array that I'm trying to sort:

[0]=>Array
 {
   [date_test] => 2016-01-01
   [last_name] => Smith
 }
[1]=>Array
{
   [date_test] => 2015-01-01
   [last_name] => Davis
 }
[2]=>Array
{
   [date_test] => 2015-01-01
   [last_name] => Smith
}

I'm trying to get the desired output:

Davis 2015-01-01
Smith 2015-01-01
Smith 2016-01-01

Here is what I'm using as code:

foreach ($total_records as &$test) {
  $test[] = $this->sortArray($test,array('patient_last_name','issued_at'));
}

sortArray( $data, $field )
{
   $field = (array) $field;
    uasort( $data, function($a, $b) use($field) {
    $retval = 0;
    foreach( $field as $fieldname )
    {
        if( $retval == 0 ) $retval = strnatcmp( $a[$fieldname],  $b[$fieldname] );
    }
    return $retval;
} );
return $data;
}

Any idea on how to to get the desired output?

Upvotes: 2

Views: 48

Answers (3)

unixmiah
unixmiah

Reputation: 3143

Try this set of code and understand the steps as you're going through it; as a result, you'll get the desired output.

<?php
/* =========================== Dataset ============================= */
$data_set = array(
  '0' => array
  (
    'date_test' => "2016-01-01",
    'last_name' => "Smith",
  ),
  '1' => array
  (
    'date_test' => "2015-01-01",
    'last_name' => "Davis",
  ),
  '2' => array
  (
    'date_test' => "2015-01-01",
    'last_name' => "Smith",
  )
);

print_r($data_set); //Check the data order
/* ========================= End Dataset =========================== */

//Order by alpha --------------------------------------------------------------
usort($data_set, function ($elem1, $elem2) {
     return strcmp($elem1['last_name'], $elem2['last_name']);
});

print_r($data_set); //Check the data set

/* =========================== End order by alpha ============================= */

//Order date by ASC order -----------------------------------------------------
foreach ($data_set as $key => $part) {
       $sort[$key] = strtotime($part['date_test']);
}
array_multisort($sort, SORT_ASC, $data_set);  //SORT_ASC sets date_test to be order in the reverse direction where SORT_DESC does the complete opposite

print_r($data_set); //Check data set once again

/* ============================ End order by date ============================= */
echo "<br><br>";

foreach ($data_set as $var){
echo "\n", $var['last_name'], "\t\t", $var['date_test']; echo "<br>";
}


/* ---- Final Dataset

Array ( [0] => Array ( [date_test] => 2016-01-01 [last_name] => Smith ) [1] => Array ( [date_test] => 2015-01-01 [last_name] => Davis ) [2] => Array ( [date_test] => \
2015-01-01 [last_name] => Smith ) ) Array ( [0] => Array ( [date_test] => 2015-01-01 [last_name] => Davis ) [1] => Array ( [date_test] => 2015-01-01 [last_name] => Sm\
ith ) [2] => Array ( [date_test] => 2016-01-01 [last_name] => Smith ) ) Array ( [0] => Array ( [date_test] => 2015-01-01 [last_name] => Davis ) [1] => Array ( [date_t\
est] => 2015-01-01 [last_name] => Smith ) [2] => Array ( [date_test] => 2016-01-01 [last_name] => Smith ) )

Davis 2015-01-01
Smith 2015-01-01
Smith 2016-01-01

 ---- Final Dataset */
?>

Desired output:

Davis 2015-01-01
Smith 2015-01-01
Smith 2016-01-01

enter image description here

Upvotes: 0

Patrick Murphy
Patrick Murphy

Reputation: 2329

assign your array of arrays to $mylist

Get a list of sort columns and their data to pass to array_multisort

$sort_vals = array();
foreach($mylist as $k=>$v) {
    $sort_vals['date_test'][$k] = $v['date_test'];
    $sort_vals['last_name'][$k] = $v['last_name'];
}

sort by event_type desc and then title asc

array_multisort($sort_vals['last_name'], SORT_DESC, $sort_vals['date_test'], SORT_ASC,$mylist);

Upvotes: 1

MonkeyZeus
MonkeyZeus

Reputation: 20747

I would go for something like this:

$new_data = array();

foreach($data as $v)
{
    if(!isset($new_data[strtotime($v['date_test'])]))
    {
        $new_data[strtotime($v['date_test'])] = array();
    }

    if(!isset($new_data[strtotime($v['date_test'])][$v['last_name']]))
    {
        $new_data[strtotime($v['date_test'])][$v['last_name']] = 0;
    }

    ++$new_data[strtotime($v['date_test'])][$v['last_name']];
}

ksort($new_data);

foreach($new_data as $date=>&$names)
{
    ksort($names);

    foreach($names as $name=>$amount)
    {
        echo str_repeat(date('Y-m-d', $date).' '.$name."\n", $amount);
    }
}

Upvotes: 0

Related Questions