Web

Сортировка многомерного массива по нескольким столбцам

Я пытаюсь отсортировать многомерный массив по нескольким ключам и понятия не имею, с чего начать. Я посмотрел на uasort(), но не совсем уверен, как написать функцию для того, что мне нужно. Мне нужно отсортировать по «state», затем по «event_type», затем по «date_start». Мой массив выглядит следующим образом:

[

    ['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']

]

Мой желаемый результат таков:

[

    ['ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party',   'state' => 'california']

    ['ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york'],

    ['ID' => 1, 'title' => 'Boring Meeting',  'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york'],

    ['ID' => 3, 'title' => 'Mario Party',     'date_start' => '2010-07-22', 'event_type' => 'party',   'state' => 'new-york'],

]

 

Ответ 1

Тебе нужно использовать 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')

);

# получить список колонок сортировки и их данные для передачи в array_multisort

$sort = array();

foreach($mylist as $k=>$v) {

    $sort['title'][$k] = $v['title'];

    $sort['event_type'][$k] = $v['event_type'];

}

# сортировка по event_type по убыванию, а затем по title по возрастанию

array_multisort($sort['event_type'], SORT_DESC, $sort['title'], SORT_ASC,$mylist);

 

Начиная с PHP 5.5.0:

array_multisort(array_column($mylist, 'event_type'), SORT_DESC,

                array_column($mylist, 'title'),      SORT_ASC,

                $mylist);

 

$mylist теперь:

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',

  ),

)

 

Ответ 2

PHP7 делает сортировку по нескольким столбцам СУПЕРлегкой с помощью оператора (<=>), он же «Комбинированный оператор сравнения» или «Оператор трехстороннего сравнения».

Ресурс: https://wiki.php.net/rfc/combined-comparison-operator

Сортировка по нескольким столбцам так же проста, как запись сбалансированных/реляционных массивов с обеих сторон оператора. Когда значение $a находится слева от оператора «<=>», а значение $b - справа, используется сортировка ASCending. Когда значение $b находится слева от оператора «<=>», а значение $a - справа, используется сортировка DESCending. Когда оператор «<=>» сравнивает две числовые строки, он сравнивает их как числа - таким образом, вы автоматически получаете естественную сортировку. Я не использовал uasort(), потому что не вижу необходимости сохранять исходные индексы.

Код сортирует по «state» ASC, затем «event_type» ASC, затем «date_start» ASC

$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);

 

Вывод:

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',

  ),

)

Пример для PHP7.4 и выше:

usort($array, fn($a, $b) =>

    [$a['state'], $a['event_type'], $a['date_start']]

    <=>

    [$b['state'], $b['event_type'], $b['date_start']]

);

Эквивалентная техника с array_multisort() и вызовом array_column() для каждого критерия сортировки: 

array_multisort(

    array_column($array, 'state'),

    array_column($array, 'event_type'),

    array_column($array, 'date_start'),

    $array

);

 

Ответ 3

Вы можете сделать это с помощью usort. Аргумент $cmp_function может быть таким:

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

}

Для произвольного количества полей в PHP 5.3 вы можете использовать закрытия для создания функции сравнения:

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

Для произвольного количества полей различных типов в PHP 5.3:

function make_cmp($fields, $dfltcmp='strcmp') {

    # присвоить массив в случае, если у $fields нет элементов

    $fieldcmps = array();

    # назначить функцию сравнения для полей, для которых не задана функция сравнения

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

}

/**

* Приоритет выше; приоритет 2 наступает раньше, чем 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')))

 

Ответ 4

Я попытался выполнить приведенный ниже код так: 

$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')

);

вызов функции сортировки массива:

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

print_r($songs);

функция сортировки массива:

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;

}

функция обратной сортировки массива:

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;

    }

 

 

Схожие статьи

Web

Как запустить php-скрипт как процесс-демон

Поисковый алгоритм Яндекса «Королев»: список функций и особенностей
Web

Поисковый алгоритм Яндекса «Королев»: список функций и особенностей

Лучшие бесплатные платформы для создания сайтов без особых навыков
Web

Лучшие бесплатные платформы для создания сайтов без особых навыков

Web

Ошибка построения модели и контроллера в моем проекте веб-сайта