Tools Blog Learn Quizzes Smile API Log In / Sign Up
Tools Blog Learn Quizzes Smile API Log In / Sign Up
« Return to the tutorials list
We have updated our privacy policy to let you know that we use cookies to personalise content and ads. We also use cookies to analyse our traffic and we share information about your use of our site and application with our advertising and analytics partners. By using this website or our application you agree to our use of cookies. Learn more about the way this website uses cookies or remove this message.

You can read this article in: English :: Español :: русский

3 Способа Сортировки Многомерных Массивов По Ключам Или Значениям Дочерних Элементов На PHP

December 22, 2015 Difficulty: 50 / 50 Tweet
sorted lego pieces

Сортировка многомерных массивов по одному из ключей в дочерний массив часто ставит неопытных программистов в тупик. В сегодняшнем уроке я покажу вам как сделать это 3 способами - вы сами сможете определить, какой проще для вас и обеспечивает наилучшую производительность.

Предположим, что у нас есть огромный массив, вроде того, что приведен ниже, и мы должны отсортировать его по значению последнего дочернего массива - в нашем случае по ключу 'weight' (вес).

  
  <?php
  $array = [
              [
                ['name'=>'John B'],
                ['age'=>30],
                ['sizes'=>
                          [
                          'weight'=>80, 
                          'height'=>120
                          ]
                ]
              ],
              [
                ['name'=>'Marie B'],
                ['age'=>31],
                ['sizes'=>
                          [
                          'weight'=>60, 
                          'height'=>110
                          ]
                ]
              ],
              [
                ['name'=>'Carl M'],
                ['age'=>12],
                ['sizes'=>
                          [
                          'weight'=>70, 
                          'height'=>100
                          ]
                ]
              ],
              [
                ['name'=>'Mike N'],
                ['age'=>19],
                ['sizes'=>
                          [
                          'weight'=>70, 
                          'height'=>150
                          ]
                ]
              ],
              [
                ['name'=>'Nancy N'],
                ['age'=>15],
                ['sizes'=>
                          [
                          'weight'=>60, 
                          'height'=>150
                          ]
                ]
              ],
              [
                ['name'=>'Cory X'],
                ['age'=>15],
                ['sizes'=>
                          [
                          'weight'=>44, 
                          'height'=>150
                          ]
                ]
              ]
  ];
  ?>
  

1 метод сортировки - Использование usort и возвращающей функции (рекомендованный)

Это действительно очень простой способ - usort автоматически попарно прогоняет все элементы массива, сравнивает то, что вам надо и, возвращая -1 или 1 соответственно, присваивает нужный индекс элементу в результирующем массиве. В нашем случае, если 'weight' в $a меньше или равен 'weight' в $b, то содержимое $a будет иметь меньший индекс в результирующем массиве. Смотрите код:


  <?php
  //Метод 1: сортировка массива с использованием функции usort и "вами определенной возвращающей функции"
  function method1($a,$b) 
  {
    return ($a[2]["sizes"]["weight"] <= $b[2]["sizes"]["weight"]) ? -1 : 1;
  }
  usort($array, "method1");
  print_r($array);
  ?>

Пузырьковый метод - метод старой школы

Пузырьковый метод преподавали в рамках курса информатики в 90е. Этот медленный метод сортировки прогоняет массив несколько раз.

Пузырьковый метод сравнивает попарно содержимое соседних элементов массива и, при необходимости, меняет их местами. Это действие выполняется снова и снова, пока массив не будет упорядочен. В нашем примере массив прогоняется до тех пор, пока все веса с ключом $j не будут меньше, чем веса с ключом $j+1. Смотрите код:


<?php
//Метод 2: Пузырьковый метод
//поменять местами два элемента
$j=0;
$flag = true; //установить флаг смены
$temp=0;

while ( $flag )
{
  $flag = false;
  for( $j=0;  $j < count($array)-1; $j++)
  {
    if ( $array[$j][2]["sizes"]["weight"] > $array[$j+1][2]["sizes"]["weight"] )
    {
      $temp = $array[$j];
      //swap the two between each other
      $array[$j] = $array[$j+1];
      $array[$j+1]=$temp;
      $flag = true; //show that a swap occurred
    }
  }
}
print_r($array);
?>

Сделай сам

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

Задача решена достаточно просто:

Сначала создайте временный пустой массив, потом прогоните сортируемый массив и замените существующие ключи сортируемыми значениями. Пожалуйста, обратите внимание, чтобы новые ключи не повторялись, иначе вы можете потерять элементы. В нашем случае я решил использовать старые ключи и добавить их к новым, чтобы результирующий ключ выглядел как: "new_key" . "some_string" . "old_unique_key". Затем я отсортировал временный массив по ключу с использованием встроенной функции ksort() и использовал значения массива для его переиндексации. Смотрите код:

Обратите внимание, что приведенный код в некоторых случаях отработает некорректно. Например, если один из элементов 'weight' больше либо равен 100, то функция ksort может вернуть неправильный результат. В таких случаях вы можете воспользоваться ksort($temp, SORT_NATURAL).


<?php
  //Метод 3: Сделай сам
  $temp = [];
  foreach ($array as $key => $value)
    $temp[$value[2]["sizes"]["weight"] . "oldkey" . $key] = $value; //добавление уникального идентификатора, чтобы равные веса не перезаписывали друг друга
  ksort($temp); // или ksort($temp, SORT_NATURAL); в абзаце выше пояснено почему
  $array = array_values($temp);
  unset($temp);
  print_r($array);
?>

Надеюсь, вам понравился сегодняшний урок. Спасибо за внимание!

comments powered by Disqus

Better Docs For A Better Web - Mozilla Developer Network

Alerts

2017-09-21 - PHP before 5.4.42, 5.5.x before 5.5.26, and 5.6.x before 5.6.10 does not ensure that pathnames lack %00 sequences, which might allow remote attackers to read or write to arbitrary files via crafted input to an application that calls (1) a DOMDocument save method or (2) the GD imagepsloadfont function, as demonstrated by a filename\0.html attack that bypasses an intended configuration in which client users may write to only .html files. Read more ...
2017-09-21 - PHP before 5.6.7 might allow remote attackers to cause a denial of service (application crash) or possibly execute arbitrary code via an unexpected data type, related to "type confusion" issues in (1) ext/soap/php_encoding.c, (2) ext/soap/php_http.c, and (3) ext/soap/soap.c, a different issue than CVE-2015-4600. Read more ...

See All Entries...