Как отсортировать подмассивы по ведущим целым числам определенного значения столбца?

Массив ниже должен быть отсортирован по первому числу cat_url_title в возрастающем направлении.

Array
(
    [0] => Array
        (
            [cat_id] => 14
            [parent_id] => 2
            [cat_url_title] => 20-a-43m
        )

    [1] => Array
        (
            [cat_id] => 13
            [parent_id] => 2
            [cat_url_title] => 16-a-20m            
        )

    [2] => Array
        (
            [cat_id] => 12
            [parent_id] => 2
            cat_url_title] => 12-a-16m
        )
)

//get the first number
foreach( $arr as $k => $v )
{
    $segs = explode("-",$v['cat_url_title']);
    $nbr = $segs[0]; //this will be 20, 16 or 12
} 

Подмассив со значением cat_url_title, начинающимся с 12, должен стать $arr[0], 16 должен остаться как $arr[1], а 20 должен переместиться в $arr[2].

Как я могу этого добиться?


person stef    schedule 06.05.2011    source источник


Ответы (6)


вы на правильном пути, после получения первых чисел создайте новый массив, содержащий число в качестве ключа и содержимое массива в качестве значения:

$newArray = array();
foreach($arr as $k => $v)
{
  $segs = explode("-", $v['cat_url_title']);
  $newArray[ $segs[0] ] = $v;
}
ksort($newArray);
print_r($newArray);

это должно работать.

person Joshua - Pendo    schedule 06.05.2011
comment
простите! Новичок в Stackoverflow, это не разрешено полностью или это просто рекомендация не давать полных решений? - person Joshua - Pendo; 06.05.2011
comment
Руководство от себя :) Если вы наведете мышь на тег домашнего задания, о котором идет речь, вы увидите его описание. В нем говорится, что задавать вопросы о домашних заданиях разрешено, при условии, что они задаются честно, объясняют проблему и прилагают достаточные усилия. Это заставляет меня думать, что ответы также должны быть даны, чтобы автор должен проявить некоторые усилия. - person binaryLV; 06.05.2011
comment
Работает! Просто интересно, что определяет, является ли вопрос домашним заданием? Я закончил десятилетие назад :) - person stef; 06.05.2011
comment
P.S. Другие типы вопросов иногда требуют полных решений, иногда они требуют только некоторых рекомендаций (псевдокод или что-то в этом роде) - в зависимости от типа проблемы. Это всего лишь частный случай - домашнее задание, поэтому ИМХО мы должны дать ему подумать и просто помочь решить проблему (а не решить ее вместо него). Это лучшее, что мы можем сделать, чтобы помочь ему когда-нибудь стать великим программистом :) - person binaryLV; 06.05.2011
comment
@stef, ну... Вопрос отмечен как домашнее задание. Тогда надо спросить у KingCrunch, зачем он добавил этот тег :) В любом случае, пока это работает, советую заглянуть в функцию usort(), а также посмотреть ссылку, которую дал p4bl0. PHP имеет обширный набор функций для работы с массивами. - person binaryLV; 06.05.2011
comment
И еще один момент: что происходит, когда несколько элементов массива имеют одинаковую cat_url_title (или, по крайней мере, одну и ту же первую ее часть)? ;) - person binaryLV; 06.05.2011
comment
Я предполагаю, что первое число является уникальным идентификатором. Если нет, то вам, возможно, придется расширить функцию. Кстати, точка взята из домашней части! - person Joshua - Pendo; 06.05.2011
comment
@PENDO, как прокомментировал Стеф, первое число (а также второе число) - это расстояние в метрах, например, 20-a-43m означает от 20 до 43 метров. - person binaryLV; 06.05.2011
comment
Ах, не заметил :-) Ну, в таком случае ему может понадобиться немного изменить его, например $segs[0] - (int)str_replace(m, , $segs[2]); и сортировать по разнице в расстоянии. - person Joshua - Pendo; 06.05.2011

usort()

person binaryLV    schedule 06.05.2011
comment
Ссылки поддерживают хороший ответ, но не являются хорошим ответом в одиночестве. Пожалуйста, будьте более щедры в своих знаниях и отредактируйте этот пост, чтобы он был чем-то большим, чем перенаправление. - person mickmackusa; 09.12.2019
comment
@micmackusa, хотя я согласен с тем, что было бы лучше написать более полный ответ, я хотел бы отметить, что этому ответу 8,5 лет, и что знания давно утеряны. - person binaryLV; 10.12.2019
comment
Старые ответы только по ссылкам с UV приглашают новых добровольцев подражать поведению. Не подходит для этого сайта. - person mickmackusa; 11.12.2019

См. функцию php usort().

Интересная страница о функциях сортировки массивов в php: http://us.php.net/manual/en/array.sorting.php

person p4bl0    schedule 06.05.2011
comment
Ссылки поддерживают хороший ответ, но не являются хорошим ответом в одиночестве. Пожалуйста, будьте более щедры в своих знаниях и отредактируйте этот пост, чтобы он был чем-то большим, чем перенаправление. - person mickmackusa; 09.12.2019

Один лайнер:

array_multisort(array_map('end', $array), SORT_NUMERIC, $array);

Предполагая:

$array = array (
    0 => array (
        'cat_id' => 14,
        'parent_id' => 2,
        'cat_url_title' => '20-a-43m'
    ),
    1 => array (
        'cat_id' => 13,
        'parent_id' => 2,
        'cat_url_title' => '16-a-20m'
    ),
    2 => array (
        'cat_id' => 12,
        'parent_id' => 2,
        'cat_url_title' => '12-a-16m'
    )
);
person Tomasz Durka    schedule 06.05.2011

Вот функция, которую я использую для сортировки массивов:

function array_sort($array, $on, $order='SORT_DESC' /*or SORT_ASC*/ )
    {
      $new_array = array();
      $sortable_array = array();

      if (count($array) > 0) {
          foreach ($array as $k => $v) {
              if (is_array($v)) {
                  foreach ($v as $k2 => $v2) {
                      if ($k2 == $on) {
                          $sortable_array[$k] = $v2;
                      }
                  }
              } else {
                  $sortable_array[$k] = $v;
              }
          }

          switch($order)
          {
              case 'SORT_ASC':   
                  asort($sortable_array);
              break;
              case 'SORT_DESC':
                  arsort($sortable_array);
              break;
          }

          foreach($sortable_array as $k => $v) {
              $new_array[] = $array[$k];
          }
      }
      return $new_array;
    } 

Использование:

array_sort($restaurants_top, "score", 'SORT_DESC');

$restaurants_top = список ресторанов "score" = ключ массива SORT_DESC = направление сортировки

person Andrei Stanca    schedule 06.05.2011

Предложение Томаша относительно array_multisort() — умный, декларативный, и краткий метод, который был доступен в версиях php в течение многих лет. Я бы, скорее всего, использовал array_multisort(), если бы эта задача была в моем проекте.

Я мог бы предложить для стабильности проекта (в случае расширения/изменения структуры данных) явно указать столбец для сортировки. Следующий фрагмент кода также позволяет избежать повторяющихся вызовов end().

array_multisort(array_column($array, 'cat_url_title'), SORT_NUMERIC, $array);

Я покажу пару современных альтернатив в качестве академического упражнения.

Начиная с PHP7, оператор космического корабля также имеет краткий синтаксис. Чтобы изолировать числовую подстроку перед первым дефисом, преобразуйте строки в целые числа.

usort($array, function($a, $b) {
    return (int)$a['cat_url_title'] <=> (int)$b['cat_url_title'];
});

Начиная с PHP7.4, синтаксис стрелочной функции делает вызов usort() более кратким, но возможно, более загадочным для чтения, если вы не привыкли к синтаксису.

usort($array, fn($a, $b) => (int)$a['cat_url_title'] <=> (int)$b['cat_url_title']);

Как и почти все мои сообщения о php, вот онлайн-демонстрация, чтобы доказать, что все мои фрагменты работают так, как задумано. .

Следует избегать фрагментов на этой странице, которые повторяют входной массив несколько раз.


p.s. если вы хотите отсортировать значения cat_url_title в четырех числовых/алфавитных подстроках, вы можете записать эти подстроки в виде массивов с каждой стороны оператора космического корабля, и он будет оценивать подстроки слева направо, чтобы определить результаты сортировки.

Код: (Демо)

usort($array, function($a, $b) {
    return (preg_match_all('~[a-z]+|\d+~', $a['cat_url_title'], $out) ? $out[0] : ['','','',''])
           <=> 
           (preg_match_all('~[a-z]+|\d+~', $b['cat_url_title'], $out) ? $out[0] : ['','','','']);
});

p.p.s. Это хороший случай для version_compare(). К сожалению, для строк в моей тестовой батарее это ненадежно. Обратите внимание на конечную позицию подмассива 16-a-20n в этой демонстрации. Я считаю, что функция игнорирует последнюю букву, потому что оценка 0 между 16-a-20m и 16-a-20n.

Что касается ваших примеров строк с согласованными позициями подстрок a и m, то они отлично подходят для естественной сортировки.

Код: (Демо)

usort($array, function($a, $b) {
    return version_compare($a['cat_url_title'], $b['cat_url_title']);
});
person mickmackusa    schedule 11.12.2019