Sort multidimensional array by multiple keys

前端 未结 7 585
挽巷
挽巷 2020-11-22 10:05

I\'m trying to sort a multidimensional array by multiple keys, and I have no idea where to start. I looked at uasort, but wasn\'t quite sure how to write a function for what

相关标签:
7条回答
  • 2020-11-22 10:17

    You can do it with usort. The $cmp_function argument could be:

    function my_sorter($a, $b) {
        $c = strcmp($a['state'], $b['state']);
        if($c != 0) {
            return $c;
        }
    
        $c = strcmp($a['event_type'], $b['event_type']);
        if($c != 0) {
            return $c;
        }
    
        return strcmp($a['date_start'], $b['date_start']);
    }
    

    For an arbitrary number of fields in PHP 5.3, you can use closures to create a comparison function:

    function make_cmp($fields, $fieldcmp='strcmp') {
        return function ($a, $b) use (&$fields) {
            foreach ($fields as $field) {
                $diff = $fieldcmp($a[$field], $b[$field]);
                if($diff != 0) {
                    return $diff;
                }
            }
            return 0;
        }
    }
    
    usort($arr, make_cmp(array('state', 'event_type', 'date_start')))
    

    For an arbitrary number of fields of different types in PHP 5.3:

    function make_cmp($fields, $dfltcmp='strcmp') {
        # assign array in case $fields has no elements
        $fieldcmps = array();
        # assign a comparison function to fields that aren't given one
        foreach ($fields as $field => $cmp) {
            if (is_int($field) && ! is_callable($cmp)) {
                $field = $cmp;
                $cmp = $dfltcmp;
            }
            $fieldcmps[$field] = $cmp;
        }
        return function ($a, $b) use (&$fieldcmps) {
            foreach ($fieldcmps as $field => $cmp) {
                $diff = call_user_func($cmp, $a[$field], $b[$field]);
                if($diff != 0) {
                    return $diff;
                }
            }
            return 0;
        }
    }
    
    function numcmp($a, $b) {
        return $a - $b;
    }
    function datecmp($a, $b) {
        return strtotime($a) - strtotime($b);
    }
    /**
     * Higher priority come first; a priority of 2 comes before 1.
     */
    function make_evt_prio_cmp($priorities, $default_priority) {
        return function($a, $b) use (&$priorities) {
            if (isset($priorities[$a])) {
                $prio_a = $priorities[$a];
            } else {
                $prio_a = $default_priority;
            }
            if (isset($priorities[$b])) {
                $prio_b = $priorities[$b];
            } else {
                $prio_b = $default_priority;
            }
            return $prio_b - $prio_a;
        };
    }
    
    $event_priority_cmp = make_evt_prio_cmp(
        array('meeting' => 5, 'party' => 10, 'concert' => 7), 
        0);
    
    usort($arr, make_cmp(array('state', 'event' => $event_priority_cmp, 'date_start' => 'datecmp', 'id' => 'numcmp')))
    
    0 讨论(0)
  • 2020-11-22 10:18

    I have tried to below code and i successfully

    array code

    $songs =  array(
            '1' => array('artist'=>'Smashing Pumpkins', 'songname'=>'Soma'),
            '2' => array('artist'=>'The Decemberists', 'songname'=>'The Island'),
            '3' => array('artist'=>'Fleetwood Mac', 'songname' =>'Second-hand News')
    );
    

    call array sorting function

    $songs = subval_sort($songs,'artist'); 
    print_r($songs);
    

    array sorting funcation

    function subval_sort($a,$subkey) {
        foreach($a as $k=>$v) {
            $b[$k] = strtolower($v[$subkey]);
        }
        asort($b);
        foreach($b as $key=>$val) {
            $c[] = $a[$key];
        }
        return $c;
    }
    

    if array reverse sorting function

    function subval_sort($a,$subkey) {
            foreach($a as $k=>$v) {
                $b[$k] = strtolower($v[$subkey]);
            }
            arsort($b);
            foreach($b as $key=>$val) {
                $c[] = $a[$key];
            }
            return $c;
        }
    
    0 讨论(0)
  • 2020-11-22 10:23
    class Sort {
        private $actual_order = 'asc';
        private $actual_field = null;
    
        public function compare_arrays($array1, $array2) {
    
            if ($array1[$this->actual_field] == $array2[$this->actual_field]) {
                return 0;
            }
            elseif ($array1[$this->actual_field] > $array2[$this->actual_field]) {
                return ($this->actual_order == 'asc' ? 1 : -1);
            }
            else {
                return ($this->actual_order == 'asc' ? -1 : 1);
            }
    
        }
    
    
        public function order_array(&$array) {
    
            usort($array, array($this, 'compare_arrays'));
    
        }
    
    
        public function __construct ($field, $actual_order = 'asc') {
            $this->actual_field = $field;
            $this->actual_order = $actual_order;
        }
    
    }
    
    // use
    
    $sort = new Sort ("state");
    
    $sort->order_array($array);
    
    0 讨论(0)
  • 2020-11-22 10:30

    PHP7 Makes sorting by multiple columns SUPER easy with the spaceship operator (<=>) aka the "Combined Comparison Operator" or "Three-way Comparison Operator".

    Resource: https://wiki.php.net/rfc/combined-comparison-operator

    Sorting by multiple columns is as simple as writing balanced/relational arrays on both sides of the operator. Easy done!

    I have not used uasort() because I don't see any need to preserve the original indexes.

    Code: (Demo)

    $array = [
        ['ID' => 1, 'title' => 'Boring Meeting', 'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york'],
        ['ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york'],
        ['ID' => 3, 'title' => 'Mario Party', 'date_start' => '2010-07-22', 'event_type' => 'party', 'state' => 'new-york'],
        ['ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party', 'state' => 'california']
    ];
    
    usort($array, function($a, $b) {
        return [$a['state'], $a['event_type'], $a['date_start']]
               <=>
               [$b['state'], $b['event_type'], $b['date_start']];
    });
    
    var_export($array);
    

    Output

    array (
      0 => 
      array (
        'ID' => 4,
        'title' => 'Duct Tape Party',
        'date_start' => '2010-07-28',
        'event_type' => 'party',
        'state' => 'california',
      ),
      1 => 
      array (
        'ID' => 2,
        'title' => 'Find My Stapler',
        'date_start' => '2010-07-22',
        'event_type' => 'meeting',
        'state' => 'new-york',
      ),
      2 => 
      array (
        'ID' => 1,
        'title' => 'Boring Meeting',
        'date_start' => '2010-07-30',
        'event_type' => 'meeting',
        'state' => 'new-york',
      ),
      3 => 
      array (
        'ID' => 3,
        'title' => 'Mario Party',
        'date_start' => '2010-07-22',
        'event_type' => 'party',
        'state' => 'new-york',
      ),
    )
    

    p.s. Arrow syntax with PHP7.4 and higher (Demo)...

    usort($array, fn($a, $b) => [$a['state'], $a['event_type'], $a['date_start']] <=> [$b['state'], $b['event_type'], $b['date_start']]);
    
    0 讨论(0)
  • 2020-11-22 10:30

    if you want to sort multi dimentional array

    first array is :

    $results['total_quote_sales_person_wise']['quote_po'];
    

    second one is :

    $results['total_quote_sales_person_wise']['quote_count'];
    

    this both multidimentional array you want to sort descending order at one time then use this code :

    array_multisort($results['total_quote_sales_person_wise']['quote_po'],SORT_DESC, $results['total_quote_sales_person_wise']['quote_count'],SORT_DESC);
    
    0 讨论(0)
  • 2020-11-22 10:35

    You need array_multisort

    $mylist = array(
        array('ID' => 1, 'title' => 'Boring Meeting', 'event_type' => 'meeting'),
        array('ID' => 2, 'title' => 'Find My Stapler', 'event_type' => 'meeting'),
        array('ID' => 3, 'title' => 'Mario Party', 'event_type' => 'party'),
        array('ID' => 4, 'title' => 'Duct Tape Party', 'event_type' => 'party')
    );
    
    # get a list of sort columns and their data to pass to array_multisort
    $sort = array();
    foreach($mylist as $k=>$v) {
        $sort['title'][$k] = $v['title'];
        $sort['event_type'][$k] = $v['event_type'];
    }
    # sort by event_type desc and then title asc
    array_multisort($sort['event_type'], SORT_DESC, $sort['title'], SORT_ASC,$mylist);
    

    As of PHP 5.5.0:

    array_multisort(array_column($mylist, 'event_type'), SORT_DESC,
                    array_column($mylist, 'title'),      SORT_ASC,
                    $mylist);
    

    $mylist is now:

    array (
      0 => 
      array (
        'ID' => 4,
        'title' => 'Duct Tape Party',
        'event_type' => 'party',
      ),
      1 => 
      array (
        'ID' => 3,
        'title' => 'Mario Party',
        'event_type' => 'party',
      ),
      2 => 
      array (
        'ID' => 1,
        'title' => 'Boring Meeting',
        'event_type' => 'meeting',
      ),
      3 => 
      array (
        'ID' => 2,
        'title' => 'Find My Stapler',
        'event_type' => 'meeting',
      ),
    )
    
    0 讨论(0)
提交回复
热议问题