PHP - Multiple uasort functions breaks sorting

前端 未结 3 1351
悲哀的现实
悲哀的现实 2020-12-01 22:18

I have a multidimensional array that stores people.

Array (
   id93294 => (array (
             Name => \"Tom Anderson\",
             Birthday => \         


        
3条回答
  •  抹茶落季
    2020-12-01 23:12

    Update

    I recently answered this question in a much more capable manner in the "definitive" topic on sorting multidimensional arrays. You can safely skip reading the rest of this answer and directly follow the link for a much more capable solution.

    Original answer

    The function uasort lets you define your own comparison function. Simply put all the criteria you want inside that.

    For example, to sort by birthday and then by name:

    function comparer($first, $second) {
        // First see if birthdays differ
        if ($first['birthday'] < $second['birthday']) {
            return -1;
        }
        else if ($first['birthday'] > $second['birthday']) {
            return 1;
        }
    
        // OK, birthdays are equal. What else?
        if ($first['name'] < $second['name']) {
            return -1;
        }
        else if ($first['name'] > $second['name']) {
            return 1;
        }
    
        // No more sort criteria. The two elements are equal.
        return 0;
    }
    

    I am ignoring the fact that in your example, the birthdays are not in a format that can be ordered by a simple comparison using the operator <. In practice you would convert them to a trivially-comparable format first.

    Update: if you think that maintaining a bunch of these multiple-criteria comparers could get ugly real fast, you find me in agreement. But this problem can be solved as any other in computer science: just add another level of abstraction.

    I 'll be assuming PHP 5.3 for the next example, in order to use the convenient anon function syntax. But in principle, you could do the same with create_function.

    function make_comparer() {
        $criteriaNames = func_get_args();
        $comparer = function($first, $second) use ($criteriaNames) {
            // Do we have anything to compare?
            while(!empty($criteriaNames)) {
                // What will we compare now?
                $criterion = array_shift($criteriaNames);
    
                // Do the actual comparison
                if ($first[$criterion] < $second[$criterion]) {
                    return -1;
                }
                else if ($first[$criterion] > $second[$criterion]) {
                    return 1;
                }
    
            }
    
            // Nothing more to compare with, so $first == $second
            return 0;
        };
    
        return $comparer;
    }
    

    You could then do:

    uasort($myArray, make_comparer('birthday', 'name'));
    

    This example possibly tries to be too clever; in general I don't like to use functions that do not accept their arguments by name. But in this case, the usage scenario is a very strong argument for being too clever.

提交回复
热议问题