Làm cách nào để sắp xếp các mảng và dữ liệu trong PHP?

298
deceze 2013-06-29 01:53.

Câu hỏi này nhằm mục đích tham khảo cho các câu hỏi về việc sắp xếp các mảng trong PHP. Dễ dàng nghĩ rằng trường hợp cụ thể của bạn là duy nhất và xứng đáng là một câu hỏi mới, nhưng hầu hết thực sự là những biến thể nhỏ của một trong những giải pháp trên trang này.

Nếu câu hỏi của bạn bị đóng lại là một bản sao của câu hỏi này, vui lòng yêu cầu câu hỏi của bạn chỉ được mở lại nếu bạn có thể giải thích lý do tại sao câu hỏi khác biệt rõ rệt với tất cả những câu hỏi dưới đây.

Làm cách nào để sắp xếp một mảng trong PHP?
Làm cách nào để sắp xếp một mảng phức tạp trong PHP?
Làm cách nào để sắp xếp một mảng các đối tượng trong PHP?


  1. Mảng một chiều cơ bản; Bao gồm Mảng đa chiều, bao gồm mảng đối tượng; Bao gồm Sắp xếp một mảng dựa trên mảng khác

  2. Phân loại với SPL

  3. Sắp xếp ổn định

Để biết câu trả lời thực tế bằng cách sử dụng các hàm hiện có của PHP, hãy xem 1., để biết câu trả lời chi tiết mang tính học thuật về các thuật toán sắp xếp (hàm nào của PHP thực hiện và bạn có thể cần cho các trường hợp thực sự, thực sự phức tạp), xem 2.

10 answers

170
deceze 2013-06-29 01:53.

Mảng một chiều cơ bản

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

Các chức năng sắp xếp áp dụng:

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

Sự khác biệt giữa những điều đó chỉ đơn thuần là việc các liên kết khóa-giá trị có được giữ hay không (các ahàm ""), nó có sắp xếp từ thấp đến cao hay đảo ngược (" r") hay không, nó có sắp xếp các giá trị hay khóa (" k") hay không và cách nó so sánh các giá trị (" nat" so với bình thường). Xem http://php.net/manual/en/array.sorting.php để biết tổng quan và các liên kết để biết thêm chi tiết.

Mảng đa chiều, bao gồm mảng đối tượng

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

Nếu bạn muốn sắp xếp $arraytheo khóa 'foo' của mỗi mục nhập, bạn cần có chức năng so sánh tùy chỉnh . Các hàm trên sortvà các hàm liên quan hoạt động dựa trên các giá trị đơn giản mà chúng biết cách so sánh và sắp xếp. PHP không chỉ đơn giản là "biết" phải làm gì với một giá trị phức tạp như array('foo' => 'bar', 'baz' => 42)mặc dù; vì vậy bạn cần phải nói với nó.

Để làm được điều đó, bạn cần tạo một hàm so sánh . Hàm đó nhận hai phần tử và phải trả về 0nếu các phần tử này được coi là bằng nhau, một giá trị thấp hơn 0nếu giá trị đầu tiên thấp hơn và một giá trị cao hơn 0nếu giá trị đầu tiên cao hơn. Đó là tất cả những gì cần thiết:

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

Thông thường, bạn sẽ muốn sử dụng một hàm ẩn danh làm hàm gọi lại. Nếu bạn muốn sử dụng một phương thức hoặc phương thức tĩnh, hãy xem các cách khác để chỉ định một lệnh gọi lại trong PHP .

Sau đó, bạn sử dụng một trong các chức năng sau:

Một lần nữa, chúng chỉ khác nhau về việc chúng giữ các liên kết khóa-giá trị và sắp xếp theo giá trị hoặc khóa. Đọc tài liệu của họ để biết chi tiết.

Ví dụ sử dụng:

usort($array, 'cmp');

usortsẽ lấy hai mục từ mảng và gọi cmphàm của bạn với chúng. Vì vậy cmp()sẽ được gọi với $aas array('foo' => 'bar', 'baz' => 42)$bas khác array('foo' => ..., 'baz' => ...). Sau đó, hàm trả về usortgiá trị nào trong số các giá trị lớn hơn hoặc liệu chúng có bằng nhau hay không. usortlặp lại quá trình này truyền các giá trị khác nhau cho $a$bcho đến khi mảng được sắp xếp. Các cmpchức năng sẽ được gọi nhiều lần, ít nhất là nhiều lần như có giá trị trong $array, với sự kết hợp khác nhau của các giá trị cho $a$bmỗi lần.

Để làm quen với ý tưởng này, hãy thử cách này:

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

Tất cả những gì bạn làm là xác định một cách tùy chỉnh để so sánh hai mặt hàng, đó là tất cả những gì bạn cần. Điều đó hoạt động với tất cả các loại giá trị.

Nhân tiện, điều này hoạt động trên bất kỳ giá trị nào, các giá trị không nhất thiết phải là các mảng phức tạp. Nếu bạn muốn so sánh tùy chỉnh, bạn cũng có thể thực hiện trên một dãy số đơn giản.

sort sắp xếp theo tham chiếu và không trả lại bất cứ điều gì hữu ích!

Lưu ý rằng mảng sắp xếp đúng vị trí , bạn không cần phải gán giá trị trả về cho bất kỳ thứ gì. $array = sort($array)sẽ thay thế mảng bằng true, không bằng một mảng đã sắp xếp. Chỉ sort($array);hoạt động.

So sánh số tùy chỉnh

Nếu bạn muốn sắp xếp theo bazkhóa, là số, tất cả những gì bạn cần làm là:

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

Nhờ The PoWEr oF MATH , giá trị này trả về giá trị <0, 0 hoặc> 0 tùy thuộc vào việc $athấp hơn, bằng hoặc lớn hơn $b.

Lưu ý rằng điều này sẽ không hoạt động tốt đối với floatcác giá trị, vì chúng sẽ bị giảm xuống intvà mất độ chính xác. Thay vào đó -1, hãy sử dụng các giá trị rõ ràng 01trả về.

Các đối tượng

Nếu bạn có một mảng đối tượng, nó hoạt động theo cùng một cách:

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

Chức năng

Bạn có thể làm bất cứ điều gì bạn cần bên trong một hàm so sánh, bao gồm cả các hàm gọi:

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

Dây

Lối tắt cho phiên bản so sánh chuỗi đầu tiên:

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

strcmpthực hiện chính xác những gì mong đợi cmpở đây, nó trả về -1, 0hoặc 1.

Nhà điều hành tàu vũ trụ

PHP 7 đã giới thiệu toán tử tàu vũ trụ , hợp nhất và đơn giản hóa các phép so sánh bằng / nhỏ hơn / lớn hơn so với các kiểu:

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

Sắp xếp theo nhiều trường

Nếu bạn muốn sắp xếp chủ yếu theo foo, nhưng nếu foobằng nhau cho hai phần tử, hãy sắp xếp theo baz:

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

Đối với những người quen thuộc, điều này tương đương với một truy vấn SQL với ORDER BY foo, baz.
Ngoài ra, hãy xem phiên bản viết tắt rất gọn gàng nàycách tạo một hàm so sánh động cho một số phím tùy ý .

Sắp xếp theo thứ tự thủ công, tĩnh

Nếu bạn muốn sắp xếp các phần tử thành "thứ tự thủ công" như "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);
}

Đối với tất cả những điều trên, nếu bạn đang sử dụng PHP 5.3 trở lên (và bạn thực sự nên làm như vậy), hãy sử dụng các hàm ẩn danh để có mã ngắn hơn và để tránh có một hàm toàn cục khác trôi nổi:

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

Đó là cách đơn giản để sắp xếp một mảng nhiều chiều phức tạp. Một lần nữa, hãy nghĩ về cách dạy PHP cách phân biệt mục nào trong số hai mục là "lớn hơn" ; hãy để PHP thực hiện việc sắp xếp thực tế.

Cũng đối với tất cả những điều trên, để chuyển đổi giữa thứ tự tăng dần và giảm dần, chỉ cần hoán đổi đối số $a$bxung quanh. Ví dụ:

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

Sắp xếp một mảng dựa trên mảng khác

Và sau đó là một điểm đặc biệt array_multisort, cho phép bạn sắp xếp một mảng dựa trên một mảng khác:

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

Kết quả mong đợi ở đây sẽ là:

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

Sử dụng array_multisortđể đến đó:

array_multisort($array1, $array2);

Kể từ PHP 5.5.0, bạn có thể sử dụng array_columnđể trích xuất một cột từ một mảng nhiều chiều và sắp xếp mảng trên cột đó:

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

Bạn cũng có thể sắp xếp trên nhiều cột, mỗi cột theo một trong hai hướng:

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

Kể từ PHP 7.0.0, bạn cũng có thể trích xuất các thuộc tính từ một mảng đối tượng.


Nếu bạn gặp nhiều trường hợp phổ biến hơn, vui lòng chỉnh sửa câu trả lời này.

139
Baba 2013-06-29 02:11.

Hầu hết các phương pháp cơ bản đã bị che đậy bởi sự lừa dối, tôi sẽ cố gắng xem xét các loại phân loại khác

Phân loại với 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));

Đầu ra

c
b
a

SplMaxHeap

Lớp SplMaxHeap cung cấp các chức năng chính của một đống, giữ mức tối đa ở trên cùng.

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

SplMinHeap

Lớp SplMinHeap cung cấp các chức năng chính của một đống, giữ mức tối thiểu ở trên cùng.

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

Các kiểu sắp xếp khác

Sắp xếp bong bóng

Từ bài viết trên Wikipedia về Sắp xếp bong bóng:

Sắp xếp bong bóng, đôi khi được gọi không chính xác là sắp xếp chìm, là một thuật toán sắp xếp đơn giản hoạt động bằng cách lặp đi lặp lại qua danh sách cần sắp xếp, so sánh từng cặp mục liền kề và hoán đổi chúng nếu chúng không đúng thứ tự. Việc chuyển qua danh sách được lặp lại cho đến khi không cần hoán đổi, điều này cho biết rằng danh sách đã được sắp xếp. Thuật toán lấy tên của nó từ cách các phần tử nhỏ hơn "bong bóng" lên đầu danh sách. Bởi vì nó chỉ sử dụng so sánh để hoạt động trên các phần tử, nó là một loại so sánh. Mặc dù thuật toán đơn giản, nhưng hầu hết các thuật toán sắp xếp khác đều hiệu quả hơn đối với các danh sách lớn.

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

Sắp xếp lựa chọn

Từ bài viết Wikipedia về Sắp xếp lựa chọn:

Trong khoa học máy tính, sắp xếp lựa chọn là một thuật toán sắp xếp, cụ thể là sắp xếp so sánh tại chỗ. Nó có độ phức tạp về thời gian O (n2), làm cho nó không hiệu quả trên các danh sách lớn và thường hoạt động kém hơn so với loại chèn tương tự. Sắp xếp lựa chọn được chú ý vì tính đơn giản của nó và nó có lợi thế về hiệu suất so với các thuật toán phức tạp hơn trong một số tình huống nhất định, đặc biệt khi bộ nhớ phụ bị hạn chế.

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

Sắp xếp chèn

Từ bài viết Wikipedia về phân loại Chèn:

Sắp xếp chèn là một thuật toán sắp xếp đơn giản xây dựng mảng (hoặc danh sách) được sắp xếp cuối cùng một mục tại một thời điểm. Nó kém hiệu quả hơn nhiều trên các danh sách lớn so với các thuật toán nâng cao hơn như quicksort, heapsort hoặc merge sort. Tuy nhiên, sắp xếp chèn cung cấp một số lợi thế:

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

Từ bài viết trên Wikipedia trên Shellsort:

Shellsort, còn được gọi là Shell sort hoặc Shell's method, là một loại so sánh tại chỗ. Nó tổng quát hóa một kiểu trao đổi, chẳng hạn như sắp xếp chèn hoặc sắp xếp bong bóng, bằng cách bắt đầu so sánh và trao đổi các phần tử với các phần tử cách xa nhau trước khi kết thúc với các phần tử lân cận.

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

Lược sắp xếp

Từ bài viết trên Wikipedia về sắp xếp Comb:

Comb sort là một thuật toán sắp xếp tương đối đơn giản do Wlodzimierz Dobosiewicz thiết kế ban đầu vào năm 1980. Sau đó nó được Stephen Lacey và Richard Box phát hiện lại vào năm 1991. Comb sort được cải thiện về sắp xếp bong bóng.

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

Hợp nhất sắp xếp

Từ bài viết Wikipedia về Sắp xếp hợp nhất:

Trong khoa học máy tính, sắp xếp hợp nhất (cũng thường được đánh vần là mergesort) là một thuật toán sắp xếp dựa trên so sánh O (n log n). Hầu hết các triển khai tạo ra một sắp xếp ổn định, có nghĩa là việc triển khai bảo toàn thứ tự đầu vào của các phần tử bằng nhau trong đầu ra được sắp xếp

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

Sắp xếp nhanh chóng

Từ bài viết Wikipedia trên Quicksort:

Quicksort, hoặc sắp xếp trao đổi phân vùng, là một thuật toán sắp xếp được phát triển bởi Tony Hoare, trung bình, thực hiện so sánh O (n log n) để sắp xếp n mục. Trong trường hợp xấu nhất, nó thực hiện so sánh O (n2), mặc dù hành vi này rất hiếm.

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

Sắp xếp hoán vị

Từ bài viết trên Wikipedia về Sắp xếp hoán vị:

Sắp xếp hoán vị, tiến hành bằng cách tạo ra các hoán vị có thể có của mảng / danh sách đầu vào cho đến khi phát hiện ra hoán vị được sắp xếp.

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

Sắp xếp Radix

Từ bài viết trên Wikipedia về sắp xếp Radix:

Trong khoa học máy tính, sắp xếp cơ số là một thuật toán sắp xếp số nguyên không so sánh, sắp xếp dữ liệu với các khóa số nguyên bằng cách nhóm các khóa theo các chữ số riêng lẻ có cùng vị trí và giá trị có nghĩa.

// 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;
}
43
Ja͢ck 2013-06-29 03:05.

Sắp xếp ổn định

Giả sử bạn có một mảng như thế này:

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

Và bây giờ bạn chỉ muốn sắp xếp trên chữ cái đầu tiên:

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

Kết quả là:

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

Loại không ổn định!

Người quan sát tinh ý có thể nhận thấy rằng thuật toán sắp xếp mảng (QuickSort) không tạo ra kết quả ổn định và thứ tự ban đầu giữa các từ của cùng một chữ cái đầu tiên không được giữ nguyên. Trường hợp này là nhỏ và đáng lẽ chúng ta nên so sánh toàn bộ chuỗi, nhưng hãy giả sử trường hợp sử dụng của bạn phức tạp hơn, chẳng hạn như hai loại liên tiếp trên các trường khác nhau sẽ không hủy bỏ công việc của nhau.

Phép biến đổi Schwartzian

Phép biến đổi Schwartzian , còn được gọi là thành ngữ trang trí-sắp xếp-không trang trí, có tác dụng sắp xếp ổn định với một thuật toán sắp xếp vốn không ổn định.

Đầu tiên, bạn trang trí mỗi phần tử mảng bằng một mảng khác bao gồm khóa chính (giá trị) và khóa phụ (chỉ mục hoặc vị trí của nó):

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

Điều này biến mảng thành sau:

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

Bây giờ, chúng ta điều chỉnh bước so sánh; chúng tôi so sánh chữ cái đầu tiên một lần nữa, nhưng nếu chúng giống nhau, khóa phụ được sử dụng để giữ lại thứ tự ban đầu:

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

Sau đó, chúng tôi trang trí:

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

Kết quả cuối cùng:

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

Còn về việc tái sử dụng?

Bạn phải viết lại hàm so sánh của mình để làm việc với các phần tử mảng đã biến đổi; bạn có thể không muốn chỉnh sửa các hàm so sánh tinh vi của mình, vì vậy đây là một trình bao bọc cho hàm so sánh:

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

Hãy viết bước sắp xếp bằng cách sử dụng hàm này:

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

Thì đấy! Mã so sánh nguyên sơ của bạn đã trở lại.

15
Orangepill 2013-08-20 09:16.

Kể từ PHP 5.3 với các bao đóng, bạn cũng có thể sử dụng một bao đóng để xác định thứ tự sắp xếp của mình.

Ví dụ, giả sử $ array là một mảng các đối tượng có chứa thuộc tính 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);
 }); 
9
Athari 2015-06-04 14:58.

LINQ

Trong .NET, LINQ thường được sử dụng để sắp xếp, cung cấp cú pháp đẹp hơn nhiều so với các hàm so sánh, đặc biệt khi các đối tượng cần được sắp xếp theo nhiều trường. Có một số cổng chuyển LINQ sang PHP, bao gồm cả thư viện YaLinqo *. Với nó, các mảng có thể được sắp xếp với một dòng duy nhất mà không cần viết các hàm so sánh phức tạp.

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

Các phép so sánh có thể được tùy chỉnh thêm bằng cách chuyển một lệnh gọi lại làm đối số thứ hai, ví dụ:

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

Đây, '$v->count'là cách viết tắt của function ($v) { return $v->count; }(có thể được sử dụng). Các chuỗi phương thức này trả về các trình vòng lặp, các trình vòng lặp có thể được chuyển đổi thành mảng bằng cách thêm ->toArray()vào cuối nếu cần.

Bên trong, orderByvà các phương pháp có liên quan gọi mảng sắp xếp các chức năng thích hợp ( uasort, krsort, multisort, usortvv).

LINQ chứa nhiều phương thức khác được lấy cảm hứng từ SQL: lọc, nhóm, nối, tổng hợp, v.v. Nó phù hợp nhất cho các trường hợp cần thực hiện các phép biến đổi phức tạp trên mảng và đối tượng mà không cần dựa vào cơ sở dữ liệu.

* do tôi phát triển, xem readme để biết thêm chi tiết và so sánh với các cổng LINQ khác

3
Andrew Surdu 2018-01-31 09:26.

Sắp xếp đa chiều theo giá trị khóa

Sắp xếp tự nhiên mảng nhiều chiều theo giá trị khóa và cũng giữ thứ tự ban đầu (không xáo trộn các khóa chính):

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

Trường hợp thử nghiệm:

$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
Ihor Burlachenko 2016-01-16 13:03.

Rất thuận tiện để sắp xếp các mảng với hàm đã sắp xếp từ Nspl :

Phân loại cơ bản

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

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

Sắp xếp theo kết quả chức năng

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

Sắp xếp mảng đa chiều

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

Sắp xếp mảng đối tượng

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

Phân loại với chức năng so sánh

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

Bạn có thể xem tất cả các ví dụ này ở đây .

2
GAV 2019-06-15 07:27.

Nếu bạn muốn đặt hàng theo giá trị khóa, thì bạn có thể làm điều đó một dòng, thanh lịch và rõ ràng. Điều này sẽ đặt hàng theo giá tăng dần. Sử dụng array_multisort và 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);

để sản xuất

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )
1
mickmackusa 2019-12-05 01:48.

Trang này rất toàn diện, nhưng tôi muốn bổ sung thêm một chút về tiện ích tuyệt vời của toán tử phi thuyền (toán tử so sánh ba chiều) - một đứa con tuyệt đẹp của PHP7 +.

Sử dụng toán tử tàu vũ trụ để triển khai nhiều điều kiện sắp xếp

Điều này tạo ra những bước tiến lớn trong việc giảm khối lượng mã và cải thiện khả năng đọc.

Khi viết hàm sắp xếp ( usort()/ uasort()/ uksort()) tùy chỉnh của bạn để xử lý nhiều điều kiện, bạn chỉ cần viết các mảng cân bằng ở hai bên của toán tử và trả về kết quả. Không còn khối điều kiện lồng nhau hoặc nhiều lần trả về.

Các phần tử từ cả hai phía của toán tử sẽ được chuyển từ trái sang phải, từng phần tử một và trả về đánh giá ngay khi gặp sự không ràng buộc hoặc khi tất cả các phần tử đã được so sánh.

Dữ liệu mẫu cho các cuộc trình diễn của tôi:

$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' => ''
    ]
];

Trình diễn (để tránh trang Stackoverflow phình to, vui lòng xem liên kết demo để biết kết quả đầu ra):

  • Sắp xếp logic:

    1. boolean DESC (false = 0, true = 1, do đó, trues trước falses)
    2. float ASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
      
  • Sắp xếp logic:

    1. ASC hỗn hợp
    2. đối tượng ASC
    3. boolean ASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
      
  • Sắp xếp logic:

    1. số thuộc tính của đối tượng ASC
    2. khả năng lặp lại của DESC hỗn hợp
    3. natString length 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']];
      });
      

Cú pháp này cho phép bạn sắp xếp các giá trị, kết quả chức năng, dữ liệu lồng vào nhau và hướng sắp xếp theo phong cách thanh lịch. Điều này chắc chắn đáng để đưa vào thanh công cụ php của bạn ... đối với các trường hợp khi bạn đang xử lý dữ liệu không phải cơ sở dữ liệu - vì tất nhiên SQL sẽ là một kỹ thuật hợp lý hơn nhiều.

Theo quyết định của riêng bạn, từ PHP7.4, bạn có thể sử dụng cú pháp mũi tên với các hàm ẩn danh này. Tập lệnh tương tự với cú pháp mũi tên .

0
Rizerzero 2020-03-06 09:21.

Nếu ai đó muốn một giải pháp đơn giản hơn để thao tác với các mảng, chỉ cần sử dụng gói Laravel Collection có chức năng sortBy được triển khai cho phép bạn sắp xếp theo các phím một cách đơn giản.

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

tức là, để sắp xếp đầu tiên theo a, sau đó đến b, rồi đến c, mệnh đề đúng sẽ là

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

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

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Màn hình Samsung Galaxy S9 Plus. Chủ nhật này là Ngày của Cha⁠ — trong trường hợp nó khiến bạn suy nghĩ — và thay vì mua cho anh ấy một chiếc cà vạt trong năm nay, có lẽ đã đến lúc bạn mua cho anh ấy thứ mà anh ấy sẽ thực sự sử dụng.

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Monster Hunter: World yêu thích các sự kiện chéo. Dù có nghĩa là hóa trang thành Dante của Devil May Cry, giả dạng Horizon: Zero Dawn's Aloy, hay chiến đấu với quái vật Final Fantasy, các nhiệm vụ sự kiện khác nhau của Thế giới được nâng cấp tự do so với các trò chơi khác.

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Storm Reid, Oprah Winfrey, Mindy Kaling, Reese Witherspoon và Ava DuVernay tại buổi chiếu đặc biệt của A Wrinkle in Time tại Nhà hát Walter Reade ở Thành phố New York vào ngày 7 tháng 3 năm 2018 “Ava rất mong được nói chuyện với bạn,” một trong những người của Array dư luận viên nói qua điện thoại. (Array là tập thể phân phối, nghệ thuật và vận động chính sách của Ava DuVernay tập trung vào các bộ phim của người da màu và phụ nữ.

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Mission Impossible: Rogue Nation bắt đầu ở một cấp độ khác. Theo nghĩa đen.

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

McCain, người đang làm việc cho một album mới, lần đầu tiên bước vào vòng kết nối vào tối thứ Sáu ở Nashville

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Tôi viết như thế nào

Tôi viết như thế nào

Đối với tôi, mọi thứ là về dòng đầu tiên đó và nó sẽ đưa bạn đến đâu. Một số nhà văn bị điều khiển bởi cốt truyện, sự sắp xếp tinh tế của các quân cờ, trong khi những người khác bị lôi cuốn bởi một nhân vật và khả năng thực hiện một cuộc hành trình với một người bạn hư cấu mới.

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Language