Як можна сортувати масиви та дані в PHP?


292

Це питання призначене як посилання на питання про сортування масивів у PHP. Неважко подумати, що ваш конкретний випадок є унікальним і вартим нового питання, але більшість насправді є незначними варіаціями одного з рішень на цій сторінці.

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

Як сортувати масив у PHP?
Як сортувати складний масив у PHP?
Як сортувати масив об’єктів у PHP?


  1. Основні одновимірні масиви; В т.ч. Багатовимірні масиви, в т.ч. масиви об’єктів; В т.ч. Сортування одного масиву на основі іншого

  2. Сортування за SPL

  3. Стабільний сорт

Практичну відповідь із використанням існуючих функцій PHP див. 1., для детальної академічної відповіді на алгоритми сортування (які функції PHP реалізуються та які можуть знадобитися для справді, дуже складних випадків), див. 2.


@jterry Саме тому я зробив це, щоб, нарешті, мати хороший посилання на те, щоб протистояти. Відповідаючи на кожну унікальну сніжинку окремо, нікому не допомагає. :)
деге

3
Я думаю, що люди повинні просто подивитися на php.net
Олександр Жардим

@ Алекс Ха! Абсолютно. Проблема полягає в тому, що ніхто не використовує RTFM. : D
деге

2
У нас вже є відповіді, я пропоную вам перерахувати найкращі відповіді всередині кожної відповіді, а не дублювати (або переписувати) вміст. Також масиви, як правило, розглядаються індивідуально, тому робота залишається закритими голосуваннями проти дуперів у будь-якому випадку.
хакре

1
@deceze: Якщо ніхто RTFM, ніхто також не буде RTFQA - існуючий Q&A :)
hakre

Відповіді:


164

Основні одновимірні масиви

$array = array(3, 5, 2, 8);

Застосовувані функції сортування:

  • sort
  • rsort
  • asort
  • arsort
  • natsort
  • natcasesort
  • ksort
  • krsort

Різниця між ними полягає лише в тому, чи зберігаються асоціації ключових значень (" a" функції), сортується від низьких до високих чи зворотних (" r"), сортує значення або ключі (" k") і як порівнює значення (" nat" проти звичайного). Див. Http://php.net/manual/en/array.sorting.php для огляду та посилань на додаткові деталі.

Багатовимірні масиви, включаючи масиви об'єктів

$array = array(
    array('foo' => 'bar', 'baz' => 42),
    array('foo' => ...,   'baz' => ...),
    ...
);

Якщо ви хочете сортувати $arrayза клавішею "foo" кожного запису, вам потрібна спеціальна функція порівняння . Вищезазначені sortта пов'язані з ними функції працюють на простих значеннях, які вони вміють порівнювати та сортувати. PHP не просто "знає", що робити зі складним значенням, як-от array('foo' => 'bar', 'baz' => 42)хоч; тому вам потрібно це сказати.

Для цього вам потрібно створити функцію порівняння . Ця функція 0містить два елементи і повинна повернутися, якщо ці елементи вважаються рівними, значенням меншим, ніж 0якщо перше значення є нижчим, а значення вище, ніж 0якщо перше значення вище. Це все, що потрібно:

function cmp(array $a, array $b) {
    if ($a['foo'] < $b['foo']) {
        return -1;
    } else if ($a['foo'] > $b['foo']) {
        return 1;
    } else {
        return 0;
    }
}

Часто вам потрібно буде використовувати анонімну функцію як зворотний дзвінок. Якщо ви хочете використовувати метод або статичний метод, перегляньте інші способи визначення зворотного дзвінка в PHP .

Потім ви використовуєте одну з цих функцій:

Знову ж таки, вони відрізняються лише тим, чи зберігають асоціації ключових значень і сортують за значеннями чи ключами. Прочитайте їх документацію для детальної інформації.

Приклад використання:

usort($array, 'cmp');

usortвізьме два елементи з масиву і викличе вашу cmpфункцію з ними. Так cmp()буде називатися $aяк array('foo' => 'bar', 'baz' => 42)і $bяк інше array('foo' => ..., 'baz' => ...). Потім функція повертається до того, usortяке зі значень було більшим, або вони були рівними. usortповторює цей процес, передаючи різні значення для $aта $bдо тих пір, поки масив не буде відсортований. cmpФункція буде викликатися багато разів, по крайней мере , стільки раз , скільки є значення в $array, з різними комбінаціями значень $aі $bкожен раз.

Щоб звикнути до цієї ідеї, спробуйте:

function cmp($a, $b) {
    echo 'cmp called with $a:', PHP_EOL;
    var_dump($a);
    echo 'and $b:', PHP_EOL;
    var_dump($b);
}

Все, що ви зробили, - це визначити власний спосіб порівняння двох елементів, це все, що вам потрібно. Це працює з усілякими значеннями.

До речі, це працює на будь-якому значенні, значення не повинні бути складними масивами. Якщо у вас є спеціальне порівняння, яке ви хочете зробити, ви можете зробити це і в простому масиві чисел.

sort сортує за посиланням і не повертає нічого корисного!

Зауважте, що масив сортується на місці , вам не потрібно присвоювати повернене значення нічому. $array = sort($array)замінить масив на true, а не на відсортований масив. Просто sort($array);працює.

Спеціальні числові порівняння

Якщо ви хочете сортувати за bazключовим числом, все, що вам потрібно зробити, це:

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

Завдяки PoWEr для MATH це повертає значення <0, 0 або> 0 залежно від того, чи $aє воно нижче, рівне або більше $b.

Зауважте, що це не буде добре для floatзначень, оскільки вони будуть зведені до intта втратять точність. Використовуйте явне -1, 0і 1повертати значення замість цього.

Об'єкти

Якщо у вас є масив об'єктів, він працює так само:

function cmp($a, $b) {
    return $a->baz - $b->baz;
}

Функції

Ви можете робити все, що потрібно, для функції порівняння, включаючи функції виклику:

function cmp(array $a, array $b) {
    return someFunction($a['baz']) - someFunction($b['baz']);
}

Струни

Ярлик для першої версії порівняння рядків:

function cmp(array $a, array $b) {
    return strcmp($a['foo'], $b['foo']);
}

strcmpробить саме те, що cmpтут очікується , повертається -1, 0або 1.

Оператор космічного корабля

PHP 7 представив оператора космічного корабля , який уніфікує та спрощує рівні / менші / більші за порівняння між типами:

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

Сортування за кількома полями

Якщо ви хочете сортувати в основному за foo, але якщо fooдва рівні, то сортуйте за baz:

function cmp(array $a, array $b) {
    if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
        return $cmp;
    } else {
        return $a['baz'] - $b['baz'];
    }
}

Для знайомих це еквівалентно запиту SQL з ORDER BY foo, baz.
Також дивіться цю дуже акуратну скорочену версію і як динамічно створювати таку функцію порівняння для довільної кількості клавіш .

Сортування в ручному, статичному порядку

Якщо ви хочете сортувати елементи в "ручному порядку", наприклад "foo", "bar", "baz" :

function cmp(array $a, array $b) {
    static $order = array('foo', 'bar', 'baz');
    return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}

Для всього вищесказаного, якщо ви використовуєте PHP 5.3 або вище (і вам справді слід), використовуйте анонімні функції для коротшого коду та уникайте того, щоб нова глобальна функція плавала навколо:

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

Ось таким простим може бути сортування складного багатовимірного масиву. Знову ж таки, просто подумайте з точки зору навчання PHP, як сказати, який із двох предметів є "більшим" ; нехай PHP робить власне сортування.

Крім того, для всього перерахованого вище, для переключення між порядком зростання та спадання просто поміняйте аргументи $aта $bаргументи навколо. Наприклад:

return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending

Сортування одного масиву на основі іншого

А тут є особливість array_multisort, яка дозволяє сортувати один масив на основі іншого:

$array1 = array( 4,   6,   1);
$array2 = array('a', 'b', 'c');

Очікуваний результат тут буде:

$array2 = array('c', 'a', 'b');  // the sorted order of $array1

Використовуйте, array_multisortщоб дістатися:

array_multisort($array1, $array2);

З PHP 5.5.0 ви можете використовувати array_columnдля вилучення стовпця з багатовимірного масиву та сортування масиву на цьому стовпці:

array_multisort(array_column($array, 'foo'), SORT_DESC, $array);

Станом на PHP 7.0.0 ви також можете витягувати властивості з масиву об'єктів.


Якщо у вас є частіші випадки, сміливо редагуйте цю відповідь.


Функція числового порівняння не працює для плаваючих значень; Я впевнений, ви знаєте, що я маю на увазі :)
Ja͢ck

1
Для статичного порядку я б застосував array_flip()використовувати швидший пошук місця, наприклад, $order[$a['foo']]замість array_search($a['foo'], $order).
Ja͢ck

Можливо, це буде велика редакція: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b, але якщо ви вважаєте, що це вдосконалення, і я включив усе необхідне, я можу його застосувати.
Rizier123

@ Rizier123 Я, звичайно, аплодую зусиллям, це дуже хороший запис; але я вважаю за краще, якщо ви розмістили її як окрему відповідь, навіть якщо вона дуже схожа. Ваше перезапис містить багато деталей (перехід посилання, велика таблиця тощо), але ця деталь відволікає від чіткого вступу до основної теми роботи функції порівняння, IMHO. Я чітко посилаюся на посібник кілька разів спеціально, бо саме там слід шукати таку деталь; не потрібно повторювати це тут і відволікати від основної ідеї, яку я намагаюся передати.
деге

@deceze Основна проблема, оскільки це довідкові запитання, полягає в тому, щоб відображати інформацію максимально компактно і читабельно та полегшувати користувачам пошук їх функції сортування. Я переробив декілька речей: gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b, але я все ще мушу подумати над цим, якщо це корисно і цінно, щоб опублікувати його як окрему відповідь, оскільки це дуже схожий вміст
Rizier123

139

Ну а основні методи вже охоплені обманом, я б спробував розглянути інші типи сортування

Сортування за SPL

SplHeap

class SimpleHeapSort extends SplHeap {
    public function compare($a, $b) {
        return strcmp($a, $b);
    }
}

// Let's populate our heap here (data of 2009)
$heap = new SimpleHeapSort();
$heap->insert("a");
$heap->insert("b");
$heap->insert("c");

echo implode(PHP_EOL, iterator_to_array($heap));

Вихідні дані

c
b
a

SplMaxHeap

Клас SplMaxHeap забезпечує основні функції купи, зберігаючи максимум у верхній частині.

$heap = new SplMaxHeap();
$heap->insert(1);
$heap->insert(2);
$heap->insert(3);

SplMinHeap

Клас SplMinHeap забезпечує основні функції купи, зберігаючи мінімум на вершині.

$heap = new SplMinHeap ();
$heap->insert(3);
$heap->insert(1);
$heap->insert(2);

Інші типи сортування

Сортування бульбашок

З статті Вікіпедії про сортування бульбашок:

Сортування бульбашок, який іноді неправильно називають сортуючим сортуванням, - це простий алгоритм сортування, який працює за допомогою багаторазового перегляду списку для сортування, порівняння кожної пари сусідніх елементів та заміни їх, якщо вони не в тому порядку. Перехід через список повторюється, поки не потрібні заміни, що вказує на те, що список відсортований. Алгоритм отримує свою назву від того, як менші елементи "бульбашки" до вершини списку. Оскільки він використовує лише порівняння для роботи з елементами, це сортування порівняння. Хоча алгоритм простий, більшість інших алгоритмів сортування є більш ефективними для великих списків.

function bubbleSort(array $array) {
    $array_size = count($array);
    for($i = 0; $i < $array_size; $i ++) {
        for($j = 0; $j < $array_size; $j ++) {
            if ($array[$i] < $array[$j]) {
                $tem = $array[$i];
                $array[$i] = $array[$j];
                $array[$j] = $tem;
            }
        }
    }
    return $array;
}

Вибір сортування

З статті Вікіпедії про сортування:

В інформатиці сортування відбору - це алгоритм сортування, зокрема сортування на місці. Він має часову складність O (n2), що робить його неефективним у великих списках і, як правило, гірше, ніж аналогічний спосіб вставки. Сортування вибору відзначається своєю простотою, і він має переваги в порівнянні зі складнішими алгоритмами в певних ситуаціях, особливо там, де допоміжна пам'ять обмежена.

function selectionSort(array $array) {
    $length = count($array);
    for($i = 0; $i < $length; $i ++) {
        $min = $i;
        for($j = $i + 1; $j < $length; $j ++) {
            if ($array[$j] < $array[$min]) {
                $min = $j;
            }
        }
        $tmp = $array[$min];
        $array[$min] = $array[$i];
        $array[$i] = $tmp;
    }
    return $array;
}

Сортування вставки

З статті Вікіпедії про вставку:

Сортування вставки - це простий алгоритм сортування, який будує остаточний відсортований масив (або список) один за одним. Він є набагато менш ефективним у великих списках, ніж більш досконалі алгоритми, такі як квакісорт, гипсорт або злиття. Однак сортування вставки надає ряд переваг:

function insertionSort(array $array) {
    $count = count($array);
    for($i = 1; $i < $count; $i ++) {

        $j = $i - 1;
        // second element of the array
        $element = $array[$i];
        while ( $j >= 0 && $array[$j] > $element ) {
            $array[$j + 1] = $array[$j];
            $array[$j] = $element;
            $j = $j - 1;
        }
    }
    return $array;
}

Шеллсорт

З статті Вікіпедії про Shellsort:

Шеллсорт, також відомий як сорт Шелла або метод Шелла, є місцевим порівнянням. Він узагальнює обмінний сорт, такий як вставка або сортування міхура, запускаючи порівняння та обмін елементами з елементами, які знаходяться далеко один від одного, перш ніж закінчити з сусідніми елементами.

function shellSort(array $array) {
    $gaps = array(
            1,
            2,
            3,
            4,
            6
    );
    $gap = array_pop($gaps);
    $length = count($array);
    while ( $gap > 0 ) {
        for($i = $gap; $i < $length; $i ++) {
            $tmp = $array[$i];
            $j = $i;
            while ( $j >= $gap && $array[$j - $gap] > $tmp ) {
                $array[$j] = $array[$j - $gap];
                $j -= $gap;
            }
            $array[$j] = $tmp;
        }
        $gap = array_pop($gaps);
    }
    return $array;
}

Гребінець сортування

З статті Вікіпедії про "Гребінь":

Сортування гребінців - це порівняно простий алгоритм сортування, спочатку розроблений Влоджімером Добосіевичем у 1980 році. Пізніше його було відкрито Стівеном Лейсі та Річардом Боксом у 1991 році.

function combSort(array $array) {
    $gap = count($array);
    $swap = true;
    while ( $gap > 1 || $swap ) {
        if ($gap > 1)
            $gap /= 1.25;
        $swap = false;
        $i = 0;
        while ( $i + $gap < count($array) ) {
            if ($array[$i] > $array[$i + $gap]) {
                // swapping the elements.
                list($array[$i], $array[$i + $gap]) = array(
                        $array[$i + $gap],
                        $array[$i]
                );
                $swap = true;
            }
            $i ++;
        }
    }
    return $array;
}

Злиття сортування

З статті Вікіпедії про сортування об’єднань:

В інформатиці сорт злиття (також часто написаний об'єднаний об'єкт) є алгоритмом сортування на основі O (n log n) порівняння. Більшість реалізацій створюють стабільний сорт, що означає, що реалізація зберігає порядок введення рівних елементів у відсортованому виході

function mergeSort(array $array) {
    if (count($array) <= 1)
        return $array;

    $left = mergeSort(array_splice($array, floor(count($array) / 2)));
    $right = mergeSort($array);

    $result = array();

    while ( count($left) > 0 && count($right) > 0 ) {
        if ($left[0] <= $right[0]) {
            array_push($result, array_shift($left));
        } else {
            array_push($result, array_shift($right));
        }
    }
    while ( count($left) > 0 )
        array_push($result, array_shift($left));

    while ( count($right) > 0 )
        array_push($result, array_shift($right));

    return $result;
}

Квікорт

З статті Вікіпедії про Quicksort:

Quicksort або сортування обміну розділами - це алгоритм сортування, розроблений Тоні Хоаром, який в середньому проводить порівняння O (n log n) для сортування n елементів. У гіршому випадку він проводить порівняння O (n2), хоча така поведінка є рідкісною.

function quickSort(array $array) {
    if (count($array) == 0) {
        return $array;
    }
    $pivot = $array[0];
    $left = $right = array();
    for($i = 1; $i < count($array); $i ++) {
        if ($array[$i] < $pivot) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }
    return array_merge(quickSort($left), array(
            $pivot
    ), quickSort($right));
}

Перестановка сортування

З статті Вікіпедії про перестановку сортування:

Сортування перестановок, яке відбувається шляхом генерації можливих перестановок вхідного масиву / списку до виявлення відсортованого.

function permutationSort($items, $perms = array()) {
    if (empty($items)) {
        if (inOrder($perms)) {
            return $perms;
        }
    } else {
        for($i = count($items) - 1; $i >= 0; -- $i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            $res = permutationSort($newitems, $newperms);
            if ($res) {
                return $res;
            }
        }
    }
}

function inOrder($array) {
    for($i = 0; $i < count($array); $i ++) {
        if (isset($array[$i + 1])) {
            if ($array[$i] > $array[$i + 1]) {
                return False;
            }
        }
    }
    return True;
}

Радікс сортування

З статті Вікіпедії про сорт Radix:

В інформатиці сортировка radix - це порівняльний алгоритм сортування цілих чисел, який сортує дані за цілими ключами, групуючи ключі за окремими цифрами, які мають однакове значне положення та значення.

// Radix Sort for 0 to 256
function radixSort($array) {
    $n = count($array);
    $partition = array();

    for($slot = 0; $slot < 256; ++ $slot) {
        $partition[] = array();
    }

    for($i = 0; $i < $n; ++ $i) {
        $partition[$array[$i]->age & 0xFF][] = &$array[$i];
    }

    $i = 0;

    for($slot = 0; $slot < 256; ++ $slot) {
        for($j = 0, $n = count($partition[$slot]); $j < $n; ++ $j) {
            $array[$i ++] = &$partition[$slot][$j];
        }
    }
    return $array;
}

4
@deceze ти висвітлив усі основи .. Мені довелося шукати інший спосіб бути актуальним :)
Баба

5
Я не бачу нічого поганого з більш академічними методами сортування :) набагато менш корисні для більшості програм, але іноді їх можуть попросити / потрібні, зручні мати посилання, тим більше, що я забув про більшість із них із часом
Дейв

Власне, для швидкого сортування рекомендується вибирати шарнір як медіану з трьох значень: першого, середнього та останнього елементів . Це мій приклад для вибору стрижня. Це дозволяє уникнути найрізноманітнішого масиву зворотного сортування (що спричиняє O(n^2)порівняння, якщо ми використовуємо лише перший елемент як опорний)
Alma Do

Я чув, що спл працює швидше, ніж звичайне сортування масиву. Це правильно?
Jewhuq

Я погоджуюсь з Дейвом, в наш час майже fw включили те, чому я рідко згадую або використовую його.
Майк Нгуен

43

Стабільний сорт

Скажімо, у вас такий масив:

['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']

А тепер ви хочете сортувати лише по першій букві:

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

Результат такий:

['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']

Сорт не був стабільним!

Пильний спостерігач, можливо, помітив, що алгоритм сортування масиву (QuickSort) не дав стабільного результату і що початковий порядок між словами тієї ж першої літери не збереглося. Цей випадок є тривіальним, і нам слід було б порівняти весь рядок, але припустимо, що ваш випадок використання є складнішим, наприклад, двома послідовними сортуваннями в різних полях, які не повинні скасовувати роботу один одного.

Перетворення Шварца

Трансформація Шварца , яку також називають ідіомою прикрасити-сортувати-підкреслити, впливає на стабільне сортування за властивим нестабільним алгоритмом сортування.

По-перше, ви прикрасите кожен елемент масиву іншим масивом, що містить первинний ключ (значення) та вторинний ключ (його індекс чи позицію):

array_walk($array, function(&$element, $index) {
    $element = array($element, $index); // decorate
});

Це перетворює масив у такий:

[
    ['Kale', 0], ['Kaleidoscope', 1], 
    ['Aardvark', 2], ['Apple', 3], 
    ['Leicester', 4], ['Lovely', 5]
]

Тепер ми коригуємо крок порівняння; ми знову порівнюємо першу букву, але якщо вони однакові, вторинний ключ використовується для збереження початкового замовлення:

usort($array, function($a, $b) {
    // $a[0] and $b[0] contain the primary sort key
    // $a[1] and $b[1] contain the secondary sort key
    $tmp = strcmp($a[0][0], $b[0][0]);

    if ($tmp != 0) {
        return $tmp; // use primary key comparison results
    }

    return $a[1] - $b[1]; // use secondary key
});

Після цього ми визначимо:

array_walk($array, function(&$element) {
    $element = $element[0];
});

Кінцевий результат:

['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']

А як щодо повторного використання?

Вам довелося переписати свою функцію порівняння для роботи з перетвореними елементами масиву; можливо, ви не хочете редагувати свої делікатні функції порівняння, тому ось функція порівняння:

function stablecmp($fn)
{
    return function($a, $b) use ($fn) {
        if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) {
            return $tmp;
        } else {
            return $a[1] - $b[1];
        }
    };
}

Запишемо крок сортування за допомогою цієї функції:

usort($array, stablecmp(function($a, $b) {
    return strcmp($a[0], $b[0]);
}));

Вуаля! Ваш незайманий код порівняння повернувся.


Ваша фраза "впливає на стабільний сорт із нестабільним алгоритмом сортування" стала для мене моментом "ах-ха". На сторінці вікіпедії немає жодної згадки про слово стабільний, який, як мені здається, є красою трансформації. Сором.
Тайлер Колліер

1
@TylerCollier Так, вам потрібно прочитати між рядків цієї посилання на Вікіпедію ... Я врятував вам проблеми, коли це зробити ;-)
Ja͢ck,

15

З PHP 5.3 із закриттями також можна використовувати закриття для визначення порядку вашого сортування.

Наприклад, якщо припустити, що масив $ array - це масив об'єктів, що містять властивість місяця.

 $orderArray = array("Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec");

 usort($array, function($a, $b) use ($orderArray){
       return array_search($a->month, $orderArray) - array_search($b->month, $orderArray);
 }); 

Просто пам’ятайте, що цим буде видалено будь-який попередній відносний порядок (наприклад, перший об’єкт «липень» у попередньо відсортованому списку може закінчитися наприкінці групи об’єктів липня після сортування). Див. "Стабільний сортування" вище.
Джордж Ленглі

9

LINQ

У .NET LINQ часто використовується для сортування, що забезпечує набагато приємніший синтаксис порівняно з функціями порівняння, особливо коли об’єкти потребують сортування за кількома полями. Є кілька портів LINQ до PHP, включаючи бібліотеку YaLinqo *. З його допомогою масиви можна сортувати за допомогою одного рядка без написання складних функцій порівняння.

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

Порівняння можна додатково налаштувати, передаючи зворотний виклик як другий аргумент, наприклад:

$sortedByFilenameNat  = from($objects)->orderBy('$v->filename', 'strnatcmp');

Ось '$v->count'скорочення для function ($v) { return $v->count; }(можна використовувати). Ці ланцюжки методів повертають ітератори, ітератори можуть бути перетворені в масиви, додаючи ->toArray()в кінці, якщо це необхідно.

Внутрішньо, orderByі пов'язані з ними методи викликають відповідні функції сортування масиву ( uasort, krsort, multisort, і usortт.д.).

LINQ містить багато інших методів, натхнених SQL: фільтрування, групування, об'єднання, агрегація тощо. Це найкраще підходить для тих випадків, коли складні перетворення на масивах та об'єктах потрібно виконувати, не покладаючись на бази даних.

* розроблений мною, див. readme для отримання більш детальної інформації та порівняння з іншими портами LINQ


3

Багатовимірне сортування за ключовим значенням

Натуральний вид багатовимірного масиву за значенням ключа, а також зберігайте початковий порядок (не перетасовуйте основні клавіші):

function multisortByKeyValue( $k, $arr ) {
    $ids   = array();
    $index = 1;

    foreach ( $arr as $key => $row ) {
        $ids[ $key ] = intval( $row[ $k ] ) . '-' . $index . '-' . $key;
        $index ++;
    }

    natsort( $ids );

    $arr = array_merge( $ids, $arr );

    return $arr;
}

Тестовий випадок:

$arr = array(
    'id1' => array(
        'label'    => 'ID 1',
        'priority' => 30,
    ),
    'id2' => array(
        'label'    => 'ID 2',
        'priority' => 70,
    ),
    'id3' => array(
        'label'    => 'ID 3',
        'priority' => 20,
    ),
    'id4' => array(
        'label'    => 'ID 4',
        'priority' => 30,
    ),
);

$sorted = multisortByKeyValue( 'priority', $arr );

// $sorted equals to:
/*
array (
  'id3' => array (
    'label' => 'ID 3',
    'priority' => 20,
  ),
  'id1' => array (
    'label' => 'ID 1',
    'priority' => 30,
  ),
  'id4' => array (
    'label' => 'ID 4',
    'priority' => 30,
  ),
  'id2' => array (
    'label' => 'ID 2',
    'priority' => 70,
  ),
)
*/

2

Дуже зручно сортувати масиви з відсортованою функцією від Nspl :

Основне сортування

// Sort array
$sorted = sorted([3, 1, 2]);

// Sort array in descending order
$sortedDesc = sorted([3, 1, 2], true);

Сортування за результатом функції

// Sort array by the result of a given function (order words by length)
$sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen');
$sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen');

// Sort array by the result of user-defined function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); 

// Which is the same as
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0));
$sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0));

// itemGetter(0) returns a function which takes an argument with access by index/key
// and returns the value at index 0

Сортування багатовимірного масиву

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Jack', 'age' => 25),
];
$sortedByName = sorted($users, itemGetter('name'));
$sortedByNameDesc = sorted($users, true, itemGetter('name'));

// itemGetter('name') returns a function which takes an argument with access by index/key
// and returns the value of the 'name' key

Сортування масиву об’єктів

// Lets assume we have class User(name, age) with properties name and age
// and public methods getName() and getAge()
$users = [
    new User('Robert', 20),
    new User('Alex', 30),
    new User('Jack', 25),
];

// Sort list of objects by property value (sort list of users by their name)
$sortedByName = sorted($users, propertyGetter('name'));
$sortedByNameDesc = sorted($users, true, propertyGetter('name'));

// propertyGetter('name') returns a function which takes an object
// and returns the value of its 'name' property

// Sort list of objects by method result (sort list of users by their age)
$sortedByAge = sorted($users, methodCaller('getAge'));
$sortedByAgeDesc = sorted($users, true, methodCaller('getAge'));

// methodCaller('getAge') returns a function which takes an object
// and returns the result of its getAge() method

Сортування за допомогою функції порівняння

// Sort with a comparison function (order words lexicographically with strcmp)
$sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp');

// Sort with user-defined comparison function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) {
    return chr($v1[0]) - chr($v2[0]);
});

Всі ці приклади ви можете побачити тут .


2

Якщо ви хочете замовити за ключовим значенням, то ви можете зробити це однією лінією, елегантно і чітко. Це буде впорядковано за зростанням ціни. Використовує array_multisort та array_column.

   Array([0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => coffee [price] => 9.99 ) [2] => Array ( [name] => rice [price] => 4.04 ) )

   array_multisort (array_column($array, 'price'), SORT_ASC, $array);

виробляти

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )

1

Ця сторінка дуже вичерпна, але я хочу додати трохи більше про дивовижну корисність оператора космічного корабля (оператора тристороннього порівняння) - прекрасної дитини PHP7 +.

Використання оператора космічного корабля для реалізації декількох умов сортування

Це робить значні успіхи у зменшенні розширення коду та покращенні читабельності.

Коли ви пишете власну функцію сортування ( usort()/ uasort()/ uksort()) для обробки декількох умов, вам потрібно лише написати збалансовані масиви з обох сторін оператора та повернути результат. Немає більше вкладених блоків стану або декількох повернень.

Елементи з обох сторін оператора будуть проходити ліворуч праворуч, по одному, і повертають оцінку, як тільки виникає нев'язування або коли всі елементи порівнюються.

Зразкові дані для моїх демонстрацій:

$multidimArray = [
    'a' => [
        'boolean' => true,
        'natString' => 'text10',
        'object' => (object)['prop' => 2],
        'float' => -.5,
        'mixed' => []
    ],
    'b' => [
        'boolean' => true,
        'natString' => 'text12',
        'object' => (object)['prop' => 4],
        'float' => 0,
        'mixed' => null
    ],
    'c' => [
        'boolean' => false,
        'natString' => 'text100',
        'object' => (object)['prop' => 9],
        'float' => -.5,
        'mixed' => false
    ],
    'd' => [
        'boolean' => true,
        'natString' => 'text1',
        'object' => (object)['prop' => 9],
        'float' => -5,
        'mixed' => "\0"
    ],
    'e' => [
        'boolean' => false,
        'natString' => 'text2',
        'object' => (object)['prop' => 2],
        'float' => .5,
        'mixed' => ''
    ]
];

Демонстрації (щоб уникнути розкриття сторінки Stackoverflow, перегляньте демонстраційне посилання для результатів):

  • Логіка сортування:

    1. булевий DESC (false = 0, true = 1, тому надійно перед помилками)
    2. поплавок ASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
  • Логіка сортування:

    1. змішаний ASC
    2. об'єкт ASC
    3. булева ASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
  • Логіка сортування:

    1. кількість властивостей об'єкта ASC
    2. ітерабельність змішаного DESC
    3. natString довжина ASC
    4. natString ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });

Цей синтаксис дозволяє елегантно сортувати значення, функціональні результати, глибоко вкладені дані та сортувати напрямок. Це, безумовно, варто ввести у свій інструментальний ремінь php ... для випадків, коли ви обробляєте дані, що не мають бази даних, - звичайно, SQL був би набагато розумнішою технікою.

На власний розсуд із PHP7.4 ви можете використовувати синтаксис стрілок із цими анонімними функціями. Той самий сценарій із синтаксисом стрілки .


0

Якщо хтось хоче більш простого рішення для маніпулювання масивами, просто використовуйте пакет Laravel Collection, який має реалізовану функцію sortBy, яка дозволяє сортувати за клавішами просто.

$collection->sortBy('forename')->sortBy('surname');

тобто для сортування спочатку a, потім b, потім c, правильним було б застереження

sortBy('c')->sortBy('b')->sortBy('a')

https://packagist.org/packages/tightenco/collect


-1

Існує кілька способів сортування масиву. Я згадаю деякі методи для виконання цієї задачі. Перш за все, я надам цілочисельний масив, який називається "$ числа".

$number = array(8,9,3,4,0,1,2);

Це звичайний спосіб створення масиву. Припустимо, я хочу сортувати цей масив у порядку зростання. Для цього можна використовувати метод 'sor ()'.

<?php

    $number = array(8,9,3,4,0,1,2);
    sort($number);

   foreach ($number as $value) {
       echo $value."  ";
   }
?>

Тепер розглянемо результат цього,

введіть тут опис зображення

Ви можете бачити, що друкований масив відсортований. Якщо ви хочете, щоб цей масив сортувався в порядку зменшення, для цього завдання може бути використаний метод 'rsort ()'.

<?php

     $number = array(8,9,3,4,0,1,2);
     rsort($number);

     foreach ($number as $value) {
        echo $value."  ";
     }
?>

врахуйте вихід ..

введіть тут опис зображення

Тепер масив відсортований у порядку зменшення. Ок, розглянемо асоціативний масив. Я дам асоціативний масив (Асоціативний масив означає, що масив, кожен індекс якого має унікальне ключове значення.), Як це,

$number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);

Отже, зараз я хочу сортувати цей масив у порядку зростання відповідно до їх значення. Для цього можна використовувати метод 'asort ()'.

<?php

   $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
   asort($number);

   foreach ($number as $value) {
      echo $value."  ";
    }
?>

Якщо сортувати низхідний порядок за їх значенням, може бути використаний метод 'arsort ()'. Припустимо, ви хочете сортувати цей масив відповідно до їх ключового значення. У цьому може бути використаний метод 'ksort ()'.

<?php

     $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
     ksort($number);

     foreach ($number as $value) {
         echo $value."  ";
     }
?>

Тепер розглянемо вихід. введіть тут опис зображення

Тепер масив сортується за їх ключовим значенням. Якщо ви хочете сортувати масив у порядку зменшення відповідно до їх ключового значення, може бути використаний метод 'krsort ()'.

<?php

    $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
    krsort($number);

    foreach ($number as $value) {
       echo $value."  ";
    }
?>

Тепер асоціативний масив сортується у порядку зменшення відповідно до їх ключового значення. Подивіться на вихід. введіть тут опис зображення

Ось декілька методів сортування масиву у порядку зростання чи за спаданням у php.Я сподіваюся, що ви зможете отримати ідею. Дякую!


Чи не Deceze вже охоплює це розуміння: "Різниця між ними полягає лише в тому, чи зберігаються асоціації ключових значень (функції" a "), чи сортують вони від низького до високого чи зворотного (" r "), чи це сортує значення або ключі ("k") і як порівнює значення ("nat" проти нормальних). " у прийнятій відповіді?
mickmackusa

-2

Найпростішим є використання функції usort для сортування масиву без циклу: Нижче наводиться приклад:

   $array_compare= array("0" =>4,"1"=>2,"2"=>500,"3"=>100);

Це буде відсортовано у порядку відхилення:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) > 0 ? 1 :-1;
    });

Це буде сортовано у порядку, що змінюється:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) < 0 ? 1 :-1;
    });

1
1) Приклад і код несуперечливі. 2) Це вже пояснюється з більшими подробицями у наведених вище відповідях. 3) Ви, можливо, намагаєтесь відповісти на інше запитання?
деге
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.