Andy  Gee
Andy Gee

Reputation: 3342

PHP Multidimensional sort?

I have a rather annoying array structure to work with and I need to sort it by any arbitrary key combination. 2 records are displayed below but multiple records with or without the same structure will be present when sorting is actioned.

Here are two records.

Array(

    [0] => Array
    (
        [cid] => 1
        [title] => Mr
        [first_name] => Abet
        [last_name] => Simbad
        [emails] => Array
        (
            [374] => Array
            (
                [eid] => 374
                [name] => ski lodge
                [email] => [email protected]
            )

            [373] => Array
            (
                [eid] => 373
                [name] => work
                [email] => [email protected]
            )

            [375] => Array
            (
                [eid] => 375
                [name] => personal
                [email] => [email protected]
            )
        )
    )
    [1] => Array
    (
        [cid] => 2
        [title] => Mrs
        [first_name] => Angie
        [last_name] => Stokes
        [emails] => Array
        (
            [590] => Array
            (
                [eid] => 590
                [name] => work
                [email] => [email protected]
            )
        )
    )

So if I wanted to sort by email in ascending order in the emails array, how can I get the second complete record to come first in the result array? [email protected] comes before simbad@....

Also Some records will not contain an emails array. They would be last in the result set. Any help would be much appreciated.

The array shown is a cut down version but I have addresses, notes, phones and websites in the same annoying structure. Ideally I could sort with something like

$sort = array('emails','email')
$data = sort_data_func('ASC',$sort,$data);

But anything steps in the right direction will help. :)

Here's some code I have so far

$sort = array('emails','email');
foreach($contacts as $ckey => $c){
    if(is_array($c[$sort[0]])){
        foreach($c[$sort[0]] as $key1 => $sort0){
            if($sort0[$sort[1]]!=''){
                $res[$sort[0]][$ckey][$sort[1]][] = $sort0[$sort[1]];
            }
        }
    }
}
print_r($res);

Which produces:

Array
(
    [emails] => Array
    (
        [0] => Array
        (
            [0] => [email protected]
            [1] => [email protected]
            [2] => [email protected]
        )
        [1] => Array
        (
            [0] => [email protected]
        )
    )
)

But I have no idea where to go from here.

EDIT OK I have the records in the currect order now but how can I keep the initial record ID in the resulting array? Here's what I'm using.

$direction=='ASC'

function cmp_asc($a, $b){
    $key = current(array_keys($a));
    sort($a[$key]);
    $a[$key] = current($a[$key]);
    sort($b[$key]);
    $b[$key] = current($b[$key]);
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

function cmp_desc($a, $b){
    $key = current(array_keys($a));
    asort($a[$key]);
    $a[$key] = current($a[$key]);
    asort($b[$key]);
    $b[$key] = current($b[$key]);
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

if($direction=='ASC'){
    usort($res[$sort[0]], 'cmp_asc');
}else{
    usort($res[$sort[0]], 'cmp_desc');
}

In

Array
(
    [emails] => Array
        (
            [0] => Array
                (
                    [email] => Array
                        (
                            [0] => [email protected]
                            [1] => [email protected]
                            [2] => [email protected]
                        )

                )

            [1] => Array
                (
                    [email] => Array
                        (
                            [0] => [email protected]
                        )

                )
        )
)

Out

Array
(
    [emails] => Array
        (
            [0] => Array
                (
                    [email] => Array
                        (
                            [0] => [email protected]
                        )

                )

            [1] => Array
                (
                    [email] => Array
                        (
                            [0] => [email protected]
                            [1] => [email protected]
                            [2] => [email protected]
                        )

                )

        )
)

Upvotes: 2

Views: 71

Answers (1)

C3roe
C3roe

Reputation: 96455

One of the usort functions, combined with a self-written comparison function that detects the order in which two elements should be sorted, should do the trick.

Upvotes: 2

Related Questions