PHP Сортувати масив за значенням SubArray


110

У мене є така структура масиву:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

Який найкращий спосіб замовити масив поступово на основі optionNumber?

Тож результати виглядають так:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

Відповіді:


204

Використовуйте usort.

function cmp_by_optionNumber($a, $b) {
  return $a["optionNumber"] - $b["optionNumber"];
}

...

usort($array, "cmp_by_optionNumber");

У PHP ≥5.3 замість цього слід використовувати анонімну функцію :

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

Зауважте, що обидва коди вище припускають $a['optionNumber']ціле число. Використовуйте @St. Рішення Джона Джонсона, якщо вони струнні.


У PHP ≥7.0 використовуйте оператор космічного корабля<=> замість віднімання для запобігання проблем із переповненням / усіченням.

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

1
Це насправді не допомагає мені, оскільки вимагає усортування, я надаю йому функцію для використання - це важкий біт, який я не можу
обернути

17
Ну, він просто дав тобі функцію. І вам доведеться змиритися з тим, що не завжди є вбудована функція, щоб робити те, що ви хочете, ви повинні написати це самостійно. Функції порівняння просто вимагають повернення 1, 0 або -1 із зазначенням порядку сортування для двох елементів.
Тессерекс

1
Я зазирнув далі в усорт, і це насправді досить круто. Я написав просту функцію порівняння до тієї, що була вище, однак пропустив '=='. Дякую за допомогу, хлопці
Sjwdavies

3
Тепер також як закриття: - usort ($ масив, функція ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
Joeri

1
@ KiloumapL'artélon Якщо результат такий < 0, він повідомляє функцію сортування, яка aповинна з’являтися раніше b. Якщо це > 0те bповинно з'явитися перед a.
kennytm

57

Використовуйте usort

 usort($array, 'sortByOption');
 function sortByOption($a, $b) {
   return strcmp($a['optionNumber'], $b['optionNumber']);
 }

7
@BenSinclair, це тому, що рішення Кенні - для чисел, це рішення - для рядків. Вони обидва вірні :-) +1 для цієї альтернативи.
кубілай

Для нечутливого для сортування випадку використовуйте strcasecmp замість strcmp
user570605

чи можемо ми визначити ключ для другого порядку в масиві, це означає, що ми спочатку сортуємо за допомогою параметра Number, а потім сортуємо з lastUpdated. Як це зробити?
Bhavin Thummar

16

Я використовував обидва рішення від KennyTM та AJ Quick і придумав функцію, яка може допомогти у цій проблемі для багатьох випадків, таких як використання клавіш ASC або DESC для сортування чи збереження ключів або якщо у вас є об'єкти як довіри масиву .

Ось ця функція (працює для PHP7 і вище через оператора космічного корабля):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if ($preserveKeys) {
        $c = [];
        if (is_object(reset($array))) {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v->$value);
            }
        } else {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v[$value]);
            }
        }
        $asc ? asort($b) : arsort($b);
        foreach ($b as $k => $v) {
            $c[$k] = $array[$k];
        }
        $array = $c;
    } else {
        if (is_object(reset($array))) {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            });
        } else {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            });
        }
    }

    return $array;
}

Використання:

sortBySubValue($array, 'optionNumber', true, false);

Редагувати

Перша частина може бути переписана за допомогою, uasort()і функція буде коротшою (працює для PHP7 і вище через оператора космічного корабля):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if (is_object(reset($array))) {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        });
    } else {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        });
    }
    return $array;
}

Це найкраща найкорисніша відповідь тут, повинна бути на вершині;)
Еді Будімілік

@EdiBudimilic дякую, я ціную це! До речі, я оновив свою відповідь і додав скорочену версію цієї функції :)
Пигальов Павло

1
Щоб зробити цю роботу для мене, мені довелося використовувати >(більше, ніж) замість -(мінус) при порівнянні $aта $bзначеннях, оскільки я порівнював рядки. Все ще працює, хоча.
Джеймс

1
@James Ви маєте рацію. Я змінив відповідь і додав використання оператора космічного корабля (<=>). Тепер це має працювати просто чудово.
Пігальов Павло

Чи є спосіб зробити цю справу нечутливою?
loeffel

4

Клавіші видаляються при використанні такої функції, як описана вище. Якщо ключі важливі, наступна функція підтримувала б її ... але петлі foreach є досить неефективними.

function subval_sort($a,$subkey) {
    foreach($a as $k=>$v) {
        $b[$k] = strtolower($v[$subkey]);
    }
    asort($b);
    foreach($b as $key=>$val) {
        $c[$key] = $a[$key];
    }
    return $c;
}
$array = subval_sort($array,'optionNumber');

Використовуйте arsort замість asort, якщо хочете від високого до низького.

Код кредиту: http://www.firsttube.com/read/sorting-a-multi-dimensions-array-with-php/


4

Використання array_multisort (), array_map ()

array_multisort(array_map(function($element) {
      return $element['optionNumber'];
  }, $array), SORT_ASC, $array);

print_r($array);

DEMO


2
Це просто працює дуже легко. Дякую. Все, що я мав зробити, - це змінити назву колонки, і вона спрацювала.
Kobus Myburgh

2
Це також зберігає ключі для батьківського масиву
JonnyS

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.