Как отсортировать многомерный массив по значению?

934

Как я могу отсортировать этот массив по значению ключа "order"? Несмотря на то, что значения в настоящее время являются последовательными, они не всегда будут.

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)
Теги:
arrays
multidimensional-array
sorting

9 ответов

1376
Лучший ответ

Попробуйте usort. Если вы все еще на PHP 5.2 или ранее, сначала вам нужно определить функцию сортировки:

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

Начиная с PHP 5.3, вы можете использовать анонимную функцию:

usort($myArray, function($a, $b) {
    return $a['order'] - $b['order'];
});

И, наконец, с PHP 7 вы можете использовать оператор космического корабля:

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

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

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

Если вам нужно сохранить ассоциации ключей, используйте uasort() - см. Сравнение функций сортировки массивов в руководстве

  • 2
    Моя фраза немного снята, я ее отредактирую. Я имел в виду, что если вы не используете PHP 5.3, вам нужно создать специальную функцию только для этой конкретной сортировки (что как-то не очень элегантно). В противном случае вы можете использовать анонимную функцию прямо здесь.
  • 22
    @Jonathan: Вы не можете видеть большую часть работы PHP. Он принимает массив и начинается с двух элементов, которые он передает этой пользовательской функции. Ваша функция отвечает за их сравнение: если первый элемент больше второго, верните положительное целое число, если оно меньше, верните отрицательное. Если они равны, верните 0. PHP затем отправляет два других элемента в вашу функцию и продолжает делать это, пока массив не будет отсортирован. Функция здесь очень короткая, она может быть намного сложнее, если бы вы не сравнивали целые числа.
Показать ещё 29 комментариев
282
function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii]=$va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii]=$array[$ii];
    }
    $array=$ret;
}

aasort($your_array,"order");
  • 7
    @ noc2spam Я рад помочь, но подумайте о том, чтобы последовать совету студента, который, вероятно, более эффективен и, безусловно, более аккуратен!
  • 1
    @ Лохорис, чувак, я тоже это проверяю. Вчера был бы тяжелый день в офисе, если бы я не нашел этот вопрос :-)
Показать ещё 3 комментария
262

Я использую эту функцию:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key=> $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}


array_sort_by_column($array, 'order');
  • 2
    Работает очень хорошо. Уникальное решение, способное добавить направление сортировки. Спасибо!
  • 2
    Для альтернативы, которая поддерживает направления сортировки и множество дополнительных функций, вы можете взглянуть на мой ответ здесь - у него также есть преимущество в том, что он не использует array_multisort и, следовательно, не требует предварительного $sort_col , экономя на время и память.
Показать ещё 11 комментариев
62

Я обычно использую usort и передаю свою собственную функцию сравнения. В этом случае это очень просто:

function compareOrder($a, $b)
{
  return $a['order'] - $b['order'];
}
usort($array, 'compareOrder');
  • 4
    Черт возьми, я был на 30 секунд медленнее. Разве это не $ a - $ b?
  • 3
    Я всегда ошибаюсь. Дайте мне подумать из руководства: возвращаемое значение должно быть меньше нуля, если первый аргумент считается меньше второго. Поэтому, если $a['order'] равно 3, а $b['order'] равно 6, я верну -3. Правильный?
Показать ещё 3 комментария
14
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

Это касается как букв верхнего, так и нижнего регистра.

  • 4
    Как это отвечает на вопрос сортировки по определенному ключу массива?
7

Один из способов достижения этого будет таким

    $new = [
              [
                'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
                'title' => 'Flower',
                'order' => 3,
              ],

              [
                'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
                'title' => 'Free',
                'order' => 2,
              ],

              [
                'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
                'title' => 'Ready',
                'order' => 1,
              ],
    ];

    $keys = array_column($new, 'order');

    $result = array_multisort($keys, SORT_ASC, $new);

Результат:

    Array
    (
        [0] => Array
            (
                [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
                [title] => Ready
                [order] => 1
            )

        [1] => Array
            (
                [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
                [title] => Free
                [order] => 2
            )

        [2] => Array
            (
                [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
                [title] => Flower
                [order] => 3
            )

    )
6

Чтобы отсортировать массив по значению ключа "title", используйте:

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmp сравнивает строки.

uasort() поддерживает ключи массива по мере их определения.

1

Самый гибкий подход - использовать этот метод

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

вот почему:

  • Вы можете сортировать по любой клавише (также вложенной как 'key1.key2.key3' или ['k1', 'k2', 'k3'])

  • Работает как на ассоциативных, так и не ассоциативных массивах (флаг $assoc)

  • Он не использует ссылку - возвращает новый отсортированный массив

В вашем случае это будет так просто:

$sortedArray = Arr::sortByKeys($array, 'order');

Этот метод является частью этой библиотеки.

0

Давайте посмотрим правде в глаза: php не имеет простой функции из окна, чтобы правильно обрабатывать каждый сценарий сортировки массива.

Эта процедура интуитивно понятна, что означает более быструю отладку и обслуживание:

// automatic population of array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result 
// $row[0] is the ID, but is populated out of order (comes from 
// multiple selects populating various dimensions for the same DATE 
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension']; 
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle,$tempArray)) {
        array_push($tempArray,$needle);
    }
}
  • 2
    «Посмотрим правде в глаза: php НЕ имеет простой функции« из коробки »для правильной обработки каждого сценария сортировки массива». Это именно то, для чего предназначены usort / ksort / asort ^^ '
  • 0
    QED. Спасибо за поддержку. ;)
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню