객체 필드를 기준으로 객체 배열 정렬


514

이 객체 배열을 필드 중 하나 name또는로 정렬하려면 어떻게 count해야합니까?

  Array
(
    [0] => stdClass Object
        (
            [ID] => 1
            [name] => Mary Jane
            [count] => 420
        )

    [1] => stdClass Object
        (
            [ID] => 2
            [name] => Johnny
            [count] => 234
        )

    [2] => stdClass Object
        (
            [ID] => 3
            [name] => Kathy
            [count] => 4354
        )

   ....

답변:


699

usort 사용하십시오 . 다음은 매뉴얼에서 수정 된 예입니다.

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

usort($your_data, "cmp");

두 번째 인수로 모든 호출 가능 항목 을 사용할 수도 있습니다 . 여기 몇 가지 예가 있어요.

  • 익명 함수 사용하기 (PHP 5.3부터)

    usort($your_data, function($a, $b) {return strcmp($a->name, $b->name);});
  • 수업 내에서

    usort($your_data, array($this, "cmp")); // "cmp" should be a method in the class
  • 화살표 함수 사용하기 (PHP 7.4부터)

    usort($your_data, fn($a, $b) => strcmp($a->name, $b->name));

또한 숫자 값을 비교 fn($a, $b) => $a->count - $b->count하는 경우 "비교"기능이 트릭을 수행해야합니다.


93
이것은 훌륭하지만 정렬 함수가 호출 함수와 동일한 클래스에 있으면 다음을 사용해야합니다. usort ($ your_data, array ($ this, "cmp"));
rmooney

7
@rmooney 네,하지만 수업 중일 때만 가능합니다.
cambraca


7
또는 비교 함수가 비교하려는 모델 / 객체에 있다면 (제 생각에 더 깔끔한 디자인) 다음과 같이 모델 / 객체에 전체 네임 스페이스를 포함시켜야합니다. uasort ($ members, array ( "Path \ to \ your \ Model \ Member ","compareByName "));
clauziere

3
이것은 나에게 정렬되지 않은, 가장 큰 첫 번째, 그리고 모든 나머지 내가 정렬되지 않은 반환하지 않습니다
Alberto Acuña

472

클로저를 사용하는 더 좋은 방법

usort($your_data, function($a, $b)
{
    return strcmp($a->name, $b->name);
});

이것은 PHP 문서에는 없지만 5.3 이상의 클로저를 사용하는 경우 호출 가능한 인수가 제공 될 수있는 곳에서 지원됩니다.


16
우리는 신속하게 비교 함수를 정의 할 수 있으며, 수업 시간에 사용할 수 있기 때문에 더 나은 허용 대답보다이 일을 사랑
남 G VU

11
배열 키를 유지하려면uasort()
gillytech

10
정렬 -1 * strcmp($a->name, $b->name);
디스크에 대해

17
desc를 정렬하기 위해 곱할 필요가 없습니다. args 만 바꾸십시오 :strcmp($b->name, $a->name)
zxcat

3
당신은 나와 같은 상황에 직면 할 수 있습니다. 예를 들어, 부모와 자식 클래스가있을 수 있습니다. 자식 클래스는 사용하는 함수를 재정의 usort하지만 비교 함수는 동일합니다. 이를 사용하면 protected static메서드를 호출하는 대신 클로저 코드를 복제 해야 부모 클래스에서 한 번만 정의하면됩니다.
Pere

48

정수 값을 정렬하려면 다음을 수행하십시오.

// Desc sort
usort($array,function($first,$second){
    return $first->number < $second->number;
});

// Asc sort
usort($array,function($first,$second){
    return $first->number > $second->number;
});

문자열로 업데이트 하면 동일한 레지스터 (위 또는 아래)로 변환하는 것을 잊지 마십시오

// Desc sort
usort($array,function($first,$second){
    return strtolower($first->text) < strtolower($second->text);
});

// Asc sort
usort($array,function($first,$second){
    return strtolower($first->text) > strtolower($second->text);
});

44

당신이 PHP는 OOP를 사용하는 경우 당신을 변경해야 할 수도 있습니다 :

public static function cmp($a, $b) 
{
    return strcmp($a->name, $b->name);
}

//in this case FUNCTION_NAME would be cmp
usort($your_data, array('YOUR_CLASS_NAME','FUNCTION_NAME')); 

28
usort($array, 'my_sort_function');

var_dump($array);

function my_sort_function($a, $b)
{
    return $a->name < $b->name;
}

count필드 와 동일한 코드가 사용됩니다 .

에 대한 자세한 내용 usort: http://ru2.php.net/usort

Btw, 그 어레이를 어디서 얻었습니까? 나는 데이터베이스에서 그것을 원하지 않습니까?


1
성공하면 실제로 $result포함 TRUE되며 비교는입니다 $a->name > $b->name. :)
cambraca

2
@ cambraca : 아, 참조로 배열을 받아들이지 않았습니다. Btw, OP는 수집을 정렬 해야하는 순서를 말하지 않았습니다.
zerkms

1
글쎄요, 그것은 데이터베이스입니다 :) 실제로 데이터베이스에서 데이터를 가져 오는 함수에서
Alex

3
@ 알렉스 : 왜 데이터베이스에서 정렬하지 않습니까? ORDER BY count
zerkms

1
워드 프레스의 표준 기능이기 때문에 더 복잡합니다. 플러그인을 작성하면서 wp 파일을 변경할 수 없습니다. create_function을 사용하여 예제를 시도했습니다 (클래스 내에서 사용하고 있고 함수 이름을 usort에 전달하는 방법을 모르기 때문에) : create_function('$a,$b', "return $a->count < $b->count;")하지만 작동시킬 수는 없습니다. usort는 매개 변수 2가 유효한 콜백이 될 것으로 예상합니다
Alex

9

이 기능을 사용할 수 있습니다 (PHP 버전> = 5.3에서 작동).

function sortArrayByKey(&$array,$key,$string = false,$asc = true){
    if($string){
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($asc)    return strcmp(strtolower($a{$key}), strtolower($b{$key}));
            else        return strcmp(strtolower($b{$key}), strtolower($a{$key}));
        });
    }else{
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($a[$key] == $b{$key}){return 0;}
            if($asc) return ($a{$key} < $b{$key}) ? -1 : 1;
            else     return ($a{$key} > $b{$key}) ? -1 : 1;

        });
    }
}

예:

sortArrayByKey($yourArray,"name",true); //String sort (ascending order)
sortArrayByKey($yourArray,"name",true,false); //String sort (descending order)
sortArrayByKey($yourArray,"id"); //number sort (ascending order)
sortArrayByKey($yourArray,"count",false,false); //number sort (descending order)

내가 사용 $a->{$key}하고 $b->{$key}보다는 $a[$key]$b[$key]우리가 같이 엄격하지 않고 배열 구성원에 비해 속성을 다루는, 말하기,하지만 여전히 내가 찾던 대답했다.
SteJ

구현하세요 @ 만주는 솔루션으로 예제 코드에서 SteJ의 제안은 간단 개체에 대한 작동하지만 SteJ의 수정으로 내가 그것을 시도 모든 객체 배열 작동
user2993145

6

다음 usort과 같이 사용할 수 있습니다 .

usort($array,function($first,$second){
    return strcmp($first->name, $second->name);
});

5

여기에 모든 것이 실패하면 다른 해결책이 있습니다.

$names = array(); 
foreach ($my_array as $my_object) {
    $names[] = $my_object->name; //any object field
}

array_multisort($names, SORT_ASC, $my_array);

return $my_array;

이 솔루션에 대한 오스카를 받아야합니다! ))))) 감사합니다
Imeksbank

4

여기에있는 모든 대답의 단점은 정적 필드 이름 을 사용한다는 것이므로 OOP 스타일로 조정 버전을 작성했습니다. getter 메소드를 사용한다고 가정하면이 클래스를 직접 사용하고 필드 이름을 parameter로 사용할 수 있습니다 . 아마 누군가가 유용하다고 생각합니다.

class CustomSort{

    public $field = '';

    public function cmp($a, $b)
    {
        /**
         * field for order is in a class variable $field
         * using getter function with naming convention getVariable() we set first letter to uppercase
         * we use variable variable names - $a->{'varName'} would directly access a field
         */
        return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
    }

    public function sortObjectArrayByField($array, $field)
    {
        $this->field = $field;
        usort($array, array("Your\Namespace\CustomSort", "cmp"));;
        return $array;
    }
} 

3

날짜를 정렬하려면

   usort($threads,function($first,$second){
        return strtotime($first->dateandtime) < strtotime($second->dateandtime);
    });

3

정렬 기준이되는 필드를 동적으로 결정할 수있는 간단한 대안 :

$order_by = 'name';
usort($your_data, function ($a, $b) use ($order_by)
{
    return strcmp($a->{$order_by}, $b->{$order_by});
});

익명 클래스 를 허용 하는 Closure 클래스를 기반 으로합니다. PHP 5.3부터 사용할 수 있습니다.


2

로컬 기반 문자열 비교가 필요한 경우 strcoll대신 대신 사용할 수 있습니다 strcmp.

필요한 경우 로케일 정보를 설정 하기 위해 setlocale함께 사용 하는 LC_COLLATE것을 기억 하십시오.

  usort($your_data,function($a,$b){
    setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
    return strcoll($a->name,$b->name);
  });

2

Codeigniter에서 이것을 사용하는 경우 다음 방법을 사용할 수 있습니다.

usort($jobs, array($this->job_model, "sortJobs"));  // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.

@rmooney 제안에 감사드립니다. 정말 도움이됩니다.


이 Codeigniter는 정확히 무엇입니까?
ggdx

2

영감을 얻은 덕분에 외부 $ 변환기 매개 변수도 추가해야했습니다.

usort($listable_products, function($a, $b) {
    global $translator;
    return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});

1

하나의 필드로만 정렬해야하는 경우 usort좋은 선택입니다. 그러나 여러 필드를 기준으로 정렬해야하는 경우 솔루션이 빠르게 복잡해집니다. 이 경우 YaLinqo 라이브러리 *를 사용하여 배열 및 객체에 대해 SQL과 같은 쿼리 구문을 구현할 수 있습니다. 모든 경우에 대해 예쁜 구문이 있습니다.

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

여기에 사용 '$v->count'되는 약어 function ($v) { return $v->count; }가 있습니다. 이 메소드 체인은 반복자를 반환하지만 ->toArray()필요한 경우 끝에 추가하여 배열을 얻을 수 있습니다 .

* 나에 의해 개발


1

Nspl 에서 정렬 된 함수를 사용할 수 있습니다 .

use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;

// Sort by property value
$sortedByCount = sorted($objects, propertyGetter('count'));

// Or sort by result of method call
$sortedByName = sorted($objects, methodCaller('getName'));

빌트인 기능에 의해 겉보기에 해결 된 시설을 제공하기 위해 OP가 왜 추가 라이브러리를 필요로하는지 설명하십시오
ggdx

1

이것이 유틸리티 클래스에 대한 것입니다

class Util
{
    public static function sortArrayByName(&$arrayToSort, $meta) {
        usort($arrayToSort, function($a, $b) use ($meta) {
            return strcmp($a[$meta], $b[$meta]);
        });
    }
}

불러라:

Util::sortArrayByName($array, "array_property_name");

1

이런 식으로 usort를 사용할 수 있습니다

숫자로 정렬하려면 다음을 수행하십시오.

function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

또는 Abc char :

function cmp($a, $b)
{
    return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

더보기 : https://www.php.net/manual/en/function.usort.php

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.