Как сортировать массивы и данные в PHP?

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

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

Как я сортировать массив в PHP?
Как мне сортировать комплекс массив в PHP?
Как сортировать массив объектов в PHP?


  1. основные одномерные массивы; ВКЛ. Многомерные массивы, ВКЛ. массивы объектов; ВКЛ. Сортировка одного массива на основе другого

  2. сортировка с помощью SPL

  3. стабильный вид

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

9 ответов


основные одномерные массивы

$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 возьмет два элемента из массива и вызовет ваш .

сортировка в ручной, статический заказ

если вы хотите сортировать элементы в "ручном порядке" как "фу", "бар", "баз":

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 вы также можете извлекать свойства из массива объектов.


если у вас есть более распространенные случаи, не стесняйтесь редактировать это ответ.


Ну большинство основных методов уже охвачены deceze я бы попытался посмотреть на другие типы рода

сортировка с помощью 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;
}

сортировка вставками

С статья Википедии о сортировке вставки:

Insertion sort-это простой алгоритм сортировки, который строит окончательный отсортированный массив (или список) по одному элементу за раз. Он гораздо менее эффективен в больших списках, чем более продвинутые алгоритмы, такие как quicksort, heapsort или сортировка слиянием. Однако insertion sort предоставляет несколько преимущества:

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

С статья Википедии о Shellsort:

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;
}

гребень вроде

С статья Википедии о сортировке гребней:

гребень сортировки является относительно простой алгоритм сортировки, изначально спроектированный Влодзимеж Dobosiewicz в 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;
}

сортировка слиянием

С статья Википедии о слиянии сортировка:

в информатике сортировка слиянием (также обычно пишется mergesort) является алгоритмом сортировки на основе сравнения 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:

Quicksort, или partition-exchange sort-алгоритм сортировки, разработанный Тони Хоаром, который в среднем делает 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 sort

С статья Википедии о сортировке Radix:

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

// 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;
}

стабильный вид

предположим, у вас есть такой массив:

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

и теперь вы хотите сортировать только по первой букве:

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

результат:

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

вид не был стабильным!

проницательный наблюдатель, возможно, заметил, что алгоритм сортировки массива (QuickSort) не дал стабильного результата и что исходный порядок между словами одной и той же первой буквы не был сохранен. Этот случай тривиален, и мы должны были сравнить всю строку, но предположим, что ваш прецедент сложнее, например, два последовательных вида на разных полях, которые не должны отменять работу друг друга.

преобразование Шварца

преобразование Шварца, также называемый идиомой decorate-sort-undecorate, влияет на стабильную сортировку с изначально нестабильным алгоритмом сортировки.

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

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
});

после этого мы undecorate:

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]);
}));

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


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

например, предполагая, что $array-это массив объектов, содержащих свойство month.

 $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);
 }); 

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 etc.).

LINQ, которая содержит более множество методов вдохновил на SQL: фильтрация, группировка, объединение, агрегирование и т. д. Лучше подходит для случаев, когда сложные преобразования массивов и объектов необходимо выполнять, не полагаясь на базы данных.

* разработанный мной, см. readme для более подробной информации и сравнения с другими портами LINQ


Многомерная сортировка по значению ключа

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

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,
  ),
)
*/

очень удобно сортировать массивы с помощью отсортированный


Существует несколько способов сортировки массива.Я упомяну некоторые методы выполнения этой задачи.прежде всего, я дам целочисленный массив, который называется "$numbers".

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

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

<?php

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

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

теперь рассмотрим результат этого,

enter image description here

вы можете увидеть напечатанный массив чисел сортируется. Если вы хотите, чтобы этот массив чисел сортировался по убыванию, для этой задачи можно использовать метод ' rsort ()'.

<?php

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

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

рассмотреть выход..

enter image description here

теперь массив сортируется в порядке убывания.Хорошо, давайте рассмотрим ассоциативный массив.Я дам ассоциативный массив (ассоциативный массив означает, что массив, каждый индекс которого имеет уникальное значение ключа.), например,

$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."  ";
     }
?>

Теперь рассмотрим выход. enter image description here

теперь массив сортируется в соответствии с их ключевым значением.Если вы хотите отсортировать массив по убыванию их ключевое значение, метод '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."  ";
    }
?>

теперь ассоциативный массив сортируется по убыванию в соответствии с их ключевым значением.Посмотрите на результат. enter image description here

это некоторые методы сортировки массива в порядке возрастания или убывания в php.Надеюсь, у вас появится идея.Спасибо!


самое простое-использовать функцию usort для сортировки массива без цикла : Ниже приведен пример :

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

Это вроде в порядке desending :

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

это будет сортировать в порядке asending:

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