PHP에서 배열과 데이터를 어떻게 정렬 할 수 있습니까?


292

이 질문은 PHP에서 배열 정렬에 대한 질문에 대한 참조로 사용됩니다. 특정 사례가 독특하고 새로운 질문에 합당하다고 생각하기는 쉽지만 실제로는이 페이지의 솔루션 중 하나를 약간 변형 한 것입니다.

귀하의 질문이이 질문과 중복되는 경우, 아래 질문과 다른 이유를 설명 할 수있는 경우에만 질문을 다시 열도록 요청하십시오.

PHP에서 배열을 어떻게 정렬합니까? PHP에서 복잡한 배열을
어떻게 정렬 합니까? PHP에서 객체 배열을 어떻게 정렬합니까?


  1. 기본 1 차원 배열; 포함 다차원 배열 (포함) 객체의 배열; 포함 다른 배열을 기준으로 한 배열 정렬

  2. SPL로 정렬

  3. 안정적인 정렬

PHP의 기존 함수를 사용한 실질적인 답변은 1을 참조하십시오. 정렬 알고리즘에 대한 학술적 세부 답변 (PHP의 함수가 구현하고 실제로 복잡한 경우에 필요할 있음)은 2를 참조하십시오.


@jterry 정확히, 이것이 내가 끝내야 할 좋은 참고 질문을하기 위해 이것을 만든 이유입니다. 각각의 독특한 눈송이에 개별적으로 응답하는 것은 누구에게도 도움이되지 않습니다. :)
deceze

3
나는 사람들이 단순히 php.net을보아야한다고 생각한다
Alexander Jardim

@ 알렉스 하! 물론. 문제는 : 아무도 RTFM이 아닙니다. : D
죽음

2
우리는 이미 그 답변을 가지고 있습니다. 콘텐츠를 복제하거나 다시 쓰는 대신 여기에 각 답변 안에 가장 좋은 답변을 목록 링크하십시오. 또한 어레이는 개별적으로 표시되는 경향이 있으므로 어떤 경우에도 작업이 듀프에 대해 투표권을 유지해야합니다.
hakre

1
@deceze : 아무도 RTFM이 아니라면 아무도 RTFQA도 – 기존 Q & A :)
hakre

답변:


164

기본 1 차원 배열

$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 oF MATH 덕분에 $a이보다 작거나 같거나 큰지 여부에 따라 <0, 0 또는> 0 값을 반환합니다 $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가 실제 정렬을 수행하게하십시오.

또한 위의 모든 항목에서 오름차순과 내림차순을 전환하려면 간단히 $aand $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

@deceze 참조 질문 및 답변이므로 주요 과제는 정보를 가능한 한 작고 읽기 쉽게 표시하고 사용자가 정렬 기능을 쉽게 찾을 수 있도록하는 것입니다. 나는 몇 가지를 쥐게 : gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b 는 별도의 답변으로 게시하는 것이 유용하고 가치있는 경우가 매우 유사한 내용이기 때문에하지만 난 여전히 그것에 대해 생각해야
Rizier123

139

글쎄, 가장 기본적인 방법은 이미 다른 종류의 유형을 보려고 시도 하는 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);

다른 종류의 정렬

버블 정렬

Bubble Sort에 관한 Wikipedia 기사에서 :

버블 정렬 (때로는 싱킹 정렬이라고 잘못 함)은 정렬 할 목록을 반복적으로 반복하여 정렬되는 인접한 정렬 항목을 비교하고 순서가 잘못된 경우 서로 바꾸어 사용하는 간단한 정렬 알고리즘입니다. 스왑이 필요하지 않을 때까지 목록 통과가 반복되어 목록이 정렬되었음을 나타냅니다. 이 알고리즘은 작은 요소가 "버블 (bubble)"하는 방식에서 목록의 최상위까지 이름을 가져옵니다. 비교 만 사용하여 요소를 조작하므로 비교 정렬입니다. 알고리즘은 단순하지만 다른 정렬 알고리즘은 대부분 큰 목록에 더 효율적입니다.

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

선택 정렬

에서 선택 정렬에 Wikipedia 기사 :

컴퓨터 과학에서 선택 정렬은 정렬 알고리즘, 특히 내부 비교 정렬입니다. 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;
}

삽입 정렬

삽입 정렬에 관한 Wikipedia 기사에서 :

삽입 정렬은 한 번에 한 항목 씩 최종 정렬 된 배열 (또는 목록)을 작성하는 간단한 정렬 알고리즘입니다. 퀵 정렬, 힙 정렬 또는 병합 정렬과 같은 고급 알고리즘보다 큰 목록에서 훨씬 덜 효율적입니다. 그러나 삽입 정렬에는 몇 가지 장점이 있습니다.

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

쉘 소트

ShellsortWikipedia 기사에서 :

Shell sort 또는 Shell의 방법으로도 알려진 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;
}

빗 정렬

에서 빗 정렬에 Wikipedia 기사 :

Comb sort는 1980 년 Wlodzimierz Dobosiewicz에 의해 원래 설계된 비교적 간단한 정렬 알고리즘입니다. 나중에 1991 년 Stephen Lacey와 Richard Box에 의해 재발견되었습니다. Comb sort는 버블 정렬을 향상시킵니다.

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

정렬 병합

에서 병합 정렬에 Wikipedia 기사 :

컴퓨터 과학에서, 병합 정렬 (일반적으로 철자 된 병합 정렬)은 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;
}

퀵소트

에서 퀵에 Wikipedia 기사 :

Quicksort (파티션 교환 정렬)는 Tony Hoare가 개발 한 정렬 알고리즘으로, 평균적으로 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));
}

순열 정렬

에서 순열 정렬에 Wikipedia 기사 :

순열 정렬-정렬 된 항목을 발견 할 때까지 입력 배열 / 목록의 가능한 순열을 생성하여 진행됩니다.

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

기수 정렬

에서 기수 정렬에 Wikipedia 기사 :

컴퓨터 과학에서 기수 정렬은 동일한 중요한 위치와 값을 공유하는 개별 숫자로 키를 그룹화하여 정수 키로 데이터를 정렬하는 비 비교 정수 정렬 알고리즘입니다.

// 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 당신은 모든 기본 사항을 다뤘습니다 .. 나는 관련된 다른 방법을 찾아야했다 :)
Baba

5
나는 더 학문적 인 분류 방법과 아무것도 잘못 표시되지 않습니다 : 대부분의 응용 프로그램에 많이 덜 유용하지만 때때로 그들이해야 할 수 있습니다 위해 / 필요한 것은 내가 시간이 지남에 따라 이들의 대부분에 대해 forgotton 것 특히 이후의 참조를 가지고 편리
데이브

실제로 빠른 정렬을 위해서는 피벗을 첫 번째, 중간 및 마지막 요소의 세 가지 값중앙값 으로 선택하는 것이 좋습니다 . 이것은 피벗 격리에 대한 나의 예입니다. 최악의 경우 역 정렬 된 배열을 피할 수 있습니다 ( O(n^2)첫 번째 요소 만 피벗으로 사용하는 경우 비교 가 발생 함 )
Alma Do

spl이 일반 배열 정렬보다 빠르게 작동한다고 들었습니다.
jewelhuq

나는 거의 Dave가 동의하지 않는 이유를 거의 fw에 포함시켰다.
Mike Nguyen

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

짜잔! 원래 비교 코드가 돌아 왔습니다.


"내재적으로 불안정한 정렬 알고리즘으로 안정적인 정렬에 영향을 미칩니다."라는 문구가 아-하 순간이었습니다. Wikipedia 페이지에는 안정이라는 단어에 대한 언급이 없으므로 변환의 아름다움이라고 생각됩니다. 부끄러움.
Tyler Collier

1
@TylerCollier 그래, 당신은 Wikipedia 참조의 줄 사이를 읽어야합니다 ... 나는 당신에게 그 문제를 저장했습니다 ;-)
Ja͢ck

15

클로저가있는 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);
 }); 

이렇게하면 이전의 상대 순서가 제거됩니다 (예를 들어, 사전 정렬 된 목록의 첫 번째 "7 월"개체가 정렬 후 7 월 개체 그룹의 끝에서 끝날 수 있음). 위의 "안정 정렬"을 참조하십시오.
George Langley

9

LINQ

.NET에서 LINQ는 정렬에 자주 사용되며, 특히 여러 필드로 개체를 정렬해야하는 경우 비교 기능보다 훨씬 뛰어난 구문을 제공합니다. YaLinqo 라이브러리 *를 포함하여 LINQ to PHP의 여러 포트가 있습니다 . 이를 통해 복잡한 비교 함수를 작성하지 않고도 한 줄로 배열을 정렬 할 수 있습니다.

$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에서 영감을 얻은 더 많은 메서드가 포함되어 있습니다. 데이터베이스에 의존하지 않고 배열과 개체에 대한 복잡한 변환을 수행해야하는 경우에 가장 적합합니다.

* 저에 의해 개발되었습니다. 자세한 내용 및 다른 LINQ 포트와의 비교는 readme를 참조하십시오


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 +의 아름다운 자식 인 우주선 연산자 (3 방향 비교 연산자)의 멋진 유틸리티에 대해 조금 더 추가하고 싶습니다.

우주선 연산자를 사용하여 여러 정렬 조건 구현

이것은 코드 팽창을 줄이고 가독성을 향상시키는 데 큰 진전을 이룹니다.

여러 조건을 처리 하기 위해 사용자 지정 정렬 ( 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' => ''
    ]
];

데모 (스택 오버플로 페이지 팽창을 피 하려면 출력 데모 링크 를 참조하십시오 ).

  • 정렬 로직 :

    1. 부울 DESC (false = 0, true = 1이므로 false 전에 true)
    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

누군가가 배열을 조작하는 더 간단한 솔루션을 원한다면 간단히 키별로 정렬 할 수있는 sortBy 함수가 구현 된 Laravel Collection 패키지를 사용하십시오.

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

이것이 배열을 만드는 일반적인 방법입니다. , 배열을 오름차순으로 정렬하고 싶다고 가정하면 'sort ()'메서드를 사용할 수 있습니다.

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

출력을 고려하십시오 ..

여기에 이미지 설명을 입력하십시오

이제 배열은 내림차순으로 정렬됩니다 .Ok, associative array를 고려해 보겠습니다 .Associative array (Associative array 의미, 각 인덱스에 고유 한 키 값이있는 배열)를 제공합니다.

$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 이미 이러한 통찰력을 포함하지 않습니다 그것은 여부 "가 정렬, 오름차순으로 정렬 또는 역방향인지,"(함수 (R "참조) 그 차이는 키 - 값 연관이)"을 유지 단지 여부를 " 값 또는 키를 정렬하고 ( "k") 값을 비교하는 방법 ( "nat"대 정상). " 받아 들여진 대답?
mickmackusa

-2

가장 간단한 방법은 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;
    });

오름차순으로 정렬됩니다.

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

1
1) 예제와 코드가 일치하지 않습니다. 2) 위의 답변에서 이미 자세히 설명되어 있습니다. 3) 다른 질문에 답변하려고합니까?
deceze
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.