2

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]
                        )

                )

        )
)
6
  • Standard question: what is your approach so far? Where are you stuck with your solution? Provide us with some more PHP code of you please. Commented Sep 15, 2013 at 13:00
  • OK, I'll try to make it a bit more understandable as it's in the middle of a lot of other code. My problem is accessing the last level of the array without knowing the key. I'm trying to avoid loops because the result set is in the thousands. Commented Sep 15, 2013 at 13:02
  • 1
    usort + self-written comparison function == done Commented Sep 15, 2013 at 13:21
  • usort would be great if there were only one email per record but there are multiple Commented Sep 15, 2013 at 13:32
  • Very close now, I just need to maintain the array index in the output array. Commented Sep 15, 2013 at 13:45

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.