Как я могу отсортировать многомерный массив естественным образом?

#php #arrays #sorting

#php #массивы #сортировка

Вопрос:

У меня есть такой массив:

 [
    ['number' => '419-1'],
    ['number' => '302-1'],
    ['number' => '102-1'],
    ['number' => '102-11'],
    ['number' => '203-1'],
    ['number' => '508-1'],
    ['number' => '105-1'],
    ['number' => '102-2'],
    ['number' => '302-2'],
]
  

Я хочу, чтобы вывод был таким:

 [
    ['number' => '102-1'],
    ['number' => '102-2'],
    ['number' => '102-11'],
    ['number' => '105-1'],
    ['number' => '203-1'],
    ['number' => '302-1'],
    ['number' => '302-2'],
    ['number' => '419-1'],
    ['number' => '508-1']
]
  

Проблема в том, что число хранится в виде строки. Я хочу рассматривать число как целое. Сортировка должна выполняться численно. Не сравнение строк. Я пробовал с usort, но это не помогло.

Кто-нибудь, пожалуйста, может мне помочь?

Ответ №1:

Вы хотите естественным образом отсортировать значения массива, 1, 2, 10, 20 чтобы они не сортировались как числовая строка 1, 10, 2, 20 . Результаты которого должны быть одинаковыми в PHP 5 и PHP 7.

Вы можете использовать array_multisort с флагами SORT_ASC и SORT_NATURAL вместе с array_column для извлечения значений для сортировки.

Пример https://3v4l.org/BNCe5

PHP 5.5

 array_multisort(array_column($ar, 'number'), SORT_ASC, SORT_NATURAL, $ar);
var_export($ar);
  

В качестве альтернативы вы можете использовать strnatcmp with usort .

PHP 5.3

 usort($ar, function($a, $b) {
   return strnatcmp($a['number'], $b['number']);
});
var_export($ar);
  

Результат

 array (
  0 => 
  array (
    'number' => '102-1',
  ),
  1 => 
  array (
    'number' => '102-2',
  ),
  2 => 
  array (
    'number' => '102-11',
  ),
  3 => 
  array (
    'number' => '105-1',
  ),
  4 => 
  array (
    'number' => '203-1',
  ),
  5 => 
  array (
    'number' => '302-1',
  ),
  6 => 
  array (
    'number' => '302-2',
  ),
  7 => 
  array (
    'number' => '419-1',
  ),
  8 => 
  array (
    'number' => '508-1',
  ),
)
  

Ответ №2:

 $arr =    [
        ['number' => '419-1'],
        ['number' => '419-11'],
        ['number' => '102-1'],
        ['number' => '203-1'],
        ['number' => '508-1'],
        ['number' => '105-1'],
        ['number' => '102-2'],
        ['number' => '302-2'],
    ];

    usort($arr, function($a,$b){

        $an = explode('-',$a['number']);
        $bn = explode('-',$b['number']);

        if($an[0] == $bn[0]){
            return $an[1]*1 > $bn[1]*1;
        }

        return $an[0]*1 > $bn[0]*1;

    });

    print_r($arr);
  

Комментарии:

1. Это не сортируется должным образом. Если у меня есть элемент с [‘number’ => ‘102-11’], он будет предшествовать [‘number’ => ‘102-2″]. Я хочу отсортировать его численно.

2. Я отредактировал входной и выходной массив, о котором идет речь. Я не хочу сравнивать их как строку, мне нужно сравнить их как число.

3. Обновлено в соответствии с вашими наблюдениями.

4. Ваши решения тоже работают! но мне больше нравится первый ответ в виде одной строки. Спасибо!

5. @TejasGosai Действительно. У вас все гладко, и этот флаг SORT_NATURAL очень хорош!