3

I have a multi dimensional array like this:

maildate | mag | panel | status
2-22-16 | green | 1 | pending
2-22-16 | green | 3 | completed
2-22-16 | green | 2 | working
2-23-16 | red | 1 | pending
2-22-16 | blue | 1 | complete

I need to sort by the status first, then date, then the mag and then the version. I have tried to use this function and it works good for the status, but I cannot get it to then do the date within the same status.

// function to sort mulitdimensional array by key
function array_sort($array, $on, $order=SORT_ASC){
    $new_array = array();
    $sortable_array = array();
    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
            $sortable_array[$k] = $v;
        }
    }
    switch ($order) {
        case SORT_ASC:
            asort($sortable_array);
            break;
        case SORT_DESC:
            arsort($sortable_array);
            break;
    }
    foreach ($sortable_array as $k => $v) {
        $new_array[$k] = $array[$k];
    }
}
return $new_array;
}
// sort lblist array by status
$lblist = array_sort($lblist, 'status', SORT_ASC);

I also have this function, which seems to work, but the status groups get divided up.

function sortByOrder($a, $b){
if ($b['status'] == $a['status']) {
if ($b['maildate'] == $a['maildate']) {
    if ($b['mag'] == $a['mag']) {
        return $b['panel'] - $a['panel'];
        }
    else {
        return $b['mag'] - $a['mag'];
        }
    }
else {
    return $b['maildate'] - $a['maildate'];
    }
}
else {
return $b['status'] - $a['status'];
}
}
usort($lblist, 'sortByOrder');

I thought maybe to divide the array by the status once it is sort by that to keep them together and then do the other sorts on each "sub" array.

2 Answers 2

1

Consider using array_multisort() but first capturing the inner arrays:

// RECREATE ARRAY    
$mail = array();
$mail[0]['maildate'] = '2-22-16'; $mail[0]['mag'] = 'green'; $mail[0]['panel'] = 1; $mail[0]['status'] = 'pending';
$mail[1]['maildate'] = '2-22-16'; $mail[1]['mag'] = 'green'; $mail[1]['panel'] = 3; $mail[1]['status'] = 'completed';
$mail[2]['maildate'] = '2-22-16'; $mail[2]['mag'] = 'green'; $mail[2]['panel'] = 2; $mail[2]['status'] = 'working';
$mail[3]['maildate'] = '2-23-16'; $mail[3]['mag'] = 'red';   $mail[3]['panel'] = 1; $mail[3]['status'] = 'pending';
$mail[4]['maildate'] = '2-22-16'; $mail[4]['mag'] = 'blue';  $mail[4]['panel'] = 1; $mail[4]['status'] = 'completed';

$maildate = array();
$mag = array();
$panel = array();
$status = array();

// CAPTURE INNER ARRAYS
foreach ($mail as $rows) {
    foreach ($rows as $key => $value) {
        switch ($key) {
            case 'maildate': $maildate[] = date_create_from_format('m-d-y', $value)->format('Y-m-d'); break;
            case 'mag': $mag[] = $value; break;
            case 'panel': $panel[] = $value; break;
            case 'status': $status[] = $value; break;
        }
    }
}

// APPLY MULTIPLE SORTS TO MAIN ARRAY
array_multisort($status, SORT_ASC, $maildate, SORT_ASC, 
                $mag, SORT_ASC, $panel, SORT_ASC, $mail);
Sign up to request clarification or add additional context in comments.

Comments

1

Looking back at the array in the question (though it's text and not actual code) you probably want to normalize it. Try this before the sort:

foreach($lblist as $row) {
    $array[] = array_combine($lblist[0], $row);
}

So you can extract each of the columns and sort on those in order and sort the original array based on that order. Notice that the maildate needs to be converted to a timestamp to sort correctly and mm-dd-YY is not valid with dashes -. Dashes use dd-mm-YY so you need / for mm/dd/YY. Change to SORT_ASC or SORT_DESC wherever needed:

array_multisort(array_column($array, 'status'), SORT_ASC,
                array_map('strtotime',
                    str_replace('-', '/',
                        array_column($array, 'maildate'))), SORT_ASC,
                array_column($array, 'mag'), SORT_ASC,
                array_column($array, 'panel'), SORT_ASC,
                $array);

PHP >= 5.5.0 needed for array_column() or use the PHP Implementation of array_column(). Or check http://php.net/manual/en/function.array-multisort.php and use the foreach() approach to create arrays to use in the sort.

foreach($array as $row) {
    $status[] = $row['status'];
    $date[]   = $row['maildate'];
    $mag[]    = $row['mag'];
    $panel[]  = $row['panel'];
}

Then replace the array_column() calls in the sort with the arrays ceated above.

Note: On the off chance this is coming from a database, just:

SELECT maildate, mag, panel, status FROM table_name ORDER BY status, maildate, mag, panel

Using a database function to convert maildate into a sortable format such as YYYY-mm-dd (example: http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html)

4 Comments

It is coming from a data base, but all of the elements of the array are not in the same row in the database. The status changes with each row for a given item. Only the first row has the maildate, mag, and panel. I have to do a second query to get the latest status. But that was another problem. Thanks
OK, you might ask a separate question with your database table structures and you may get a good way to query it already sorted.
The mail date is a time stamp so I used this:codearray_multisort( array_column($lblist, 'status'), SORT_ASC, array_column($lblist, 'maildate'), SORT_ASC, array_column($lblist, 'mag'), SORT_ASC, array_column($lblist, 'panel'), SORT_ASC, $lblist ); but it gives me nothing, actually stops the page from loading all the way.
Looks like I do not have array_column defined (does not exist).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.