usort

(PHP 4, PHP 5, PHP 7)

usort사용자 정의 비교 함수를 사용하여 값에 의한 배열 정렬

설명

bool usort ( array &$array , callback $cmp_function )

이 함수는 사용자 제공 비교 함수를 사용하여 값들에 의해 배열을 정렬할 것이다. 정렬하고자 하는 배열이 흔히 사용되지 않는 방법에 의해 정렬할 필요가 있으면, 이 함수를 사용해야 한다.

Note:

두 멤버가 같은 것으로 비교되면, 정렬한 배열에서 그들의 순서는 정의되지 않습니다.

Note: 이 함수는 array에 새로운 키를 할당합니다. 이 작업은 단순히 키를 재배열할 뿐만 아니라, 이미 할당되어 있는 키를 제거할 수 있습니다.

인수

array

입력 배열.

cmp_function

비교 함수는 첫번째 인수가 두번째 인수보다 작거나, 같거나, 크다고 판단되면 0 보다 작거나, 같거나, 큰 정수를 반환해야 한다.

반환값

성공 시 TRUE를, 실패 시 FALSE를 반환합니다.

변경점

버전 설명
4.1.0 새 정렬 알고리즘이 도입되었습니다. cmp_function은 같다고 비교되는 원소의 순서를 유지하지 않습니다.

예제

Example #1 usort() 예제

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

$a = array(32561);

usort ($a"cmp");

foreach (
$a as $key => $value) {
    echo 
"$key$value\n";
}
?>

위 예제의 출력:

0: 1
1: 2
2: 3
3: 5
4: 6

Note:

명백히 이런 흔한 경우에는 sort() 함수가 더욱 적절할것이다.

Example #2 다차원 배열을 사용하는 usort() 예제

<?php
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");

while (list(
$key$value) = each($fruits)) {
    echo 
"\$fruits[$key]: " $value["fruit"] . "\n";
}
?>

다차원 배열을 정렬할 때에는, $a$b는 배열의 첫번째 인덱스의 참조를 포함한다.

위 예제의 출력:

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

Example #3 객체의 멤버 함수를 사용하는 usort() 예제

<?php
class TestObj {
    var 
$name;

    function 
TestObj($name)
    {
        
$this->name $name;
    }

    
/* 정적 비교 함수: */
    
static function cmp_obj($a$b)
    {
        
$al strtolower($a->name);
        
$bl strtolower($b->name);
        if (
$al == $bl) {
            return 
0;
        }
        return (
$al $bl) ? +: -1;
    }
}

$a[] = new TestObj("c");
$a[] = new TestObj("b");
$a[] = new TestObj("d");

usort($a, array("TestObj""cmp_obj"));

foreach (
$a as $item) {
    echo 
$item->name "\n";
}
?>

위 예제의 출력:

b
c
d

참고

  • uasort() - 사용자 정의 비교 함수로 배열을 정렬하고 인덱스 연관성을 유지
  • uksort() - 사용자 정의 비교 함수를 사용하여 키에 의한 배열 정렬
  • sort() - 배열 정렬
  • asort() - 배열을 정렬하고 인덱스 상관 관계를 유지
  • arsort() - 배열을 내림차순 정렬하고 인덱스의 상관관계를 유지
  • ksort() - 키에 의한 배열 정렬
  • natsort() - "자연순" 알고리즘으로 배열 정렬
  • rsort() - 역순으로 배열 정렬

add a note add a note

User Contributed Notes 10 notes

up
18
Hayley Watson
11 years ago
As the documentation says, the comparison function needs to return an integer that is either "less than, equal to, or greater than zero". There is no requirement to restrict the value returned to -1, 0, 1.

<?php
usort
($array, function($a, $b) {
    if(
$a->integer_property > $b->integer_property) {
        return
1;
    }
    elseif(
$a->integer_property < $b->integer_property) {
        return -
1;
    }
    else {
        return
0;
    }
});
?>

can be simplified to

<?php
usort
($array, function($a, $b) {
    return
$a->integer_property - $b->integer_property;
});
?>

This of course applies to any comparison function that calculates an integer "score" for each of its arguments to decide which is "greater".
up
11
luke dot semerau at gmail dot com
15 years ago
If you need to use usort with a key in the calling method, I wrote this as a utility:
<?php

function usort_comparison($obj, $method, $key) {
   
$usorter = &new Usort($obj, $method, $key);
    return array(
$usorter, "sort");
}

class
Usort {
    function
__construct($obj, $method, $key) {
       
$this->obj = $obj;
       
$this->method = $method;
       
$this->key = $key;
    }
    function
sort($a, $b) {
        return
call_user_func_array(array($this->obj, $this->method), array($a, $b, $this->key));
    }
}

?>

<?php

require_once("util/usort.php");

class
Foo {
   
$items = array(FooBar(13), FooBar(2));
    public function
sorter() {
       
usort($this-items, usort_comparison("Foo", "_cmp", "item"));
    }

    public static function
_cmp($a, $b, $key) {
         return
strcasecmp($a->$key, $b->$key);
    }

}

class
FooBar {
    public
$item;
    function
__construct($val) {
       
$this->item = $val;
    }
}

?>

~ simple example... but in the way I need to use it was the key was used in a switch statement to choose the different member of the object to compare against dynamically (as in, sort by x or y or z)
up
13
mkr at binarywerks dot dk
22 years ago
If you want to sort an array according to another array acting as a priority list, you can use this function.

<?php
function listcmp($a, $b)
{
  global
$order;

  foreach(
$order as $key => $value)
    {
      if(
$a==$value)
        {
          return
0;
          break;
        }

      if(
$b==$value)
        {
          return
1;
          break;
        }
    }
}

$order[0] = "first";
$order[1] = "second";
$order[2] = "third";

$array[0] = "second";
$array[1] = "first";
$array[2] = "third";
$array[3] = "fourth";
$array[4] = "second";
$array[5] = "first";
$array[6] = "second";

usort($array, "listcmp");

print_r($array);
?>
up
6
sydney at totoche dot org
18 years ago
Instead of doing  :

<?php $strc = strcmp( strtolower($a[$f]), strtolower($b[$f]) ); ?>

you could do this :

<?php $strc = strcasecmp( $a[$f], $b[$f] ); ?>

which is more efficient and is does case insensitive comparison according to the current locale.
up
7
derek at luddite dot net
24 years ago
Needed a date sort and I didn't know if one was available so I wrote one. Maybe it'll help someone:

<?php
function DateSort($a,$b,$d="-") {
    if (
$a == $b) {
        return
0;
    } else { 
//Convert into dates and compare
       
list($am,$ad,$ay)=split($d,$a);
        list(
$bm,$bd,$by)=split($d,$b);
        if (
mktime(0,0,0,$am,$ad,$ay) < mktime(0,0,0,$bm,$bd,$by)) {
            return -
1;
        } else {
            return
1;
        }
    }
}
?>

$d is the delimeter
up
2
gus dot antoniassi at gmail dot com
5 years ago
This is a simple way to sort based on a "priority list":

<?php

$order
= [1,3,0,2];
$arr =   [
    [
'id' => 0 ],
    [
'id' => 1 ],
    [
'id' => 2 ],
    [
'id' => 3 ],
];

uasort(
   
$arr,
    function (
$a, $b) use ($order) {
        return
array_search($a['id'], $order) <=> array_search($b['id'], $order);
    }
);

print_r($arr);

?>

This will return:

Array
(
    [1] => Array
        (
            [id] => 1
        )

    [3] => Array
        (
            [id] => 3
        )

    [0] => Array
        (
            [id] => 0
        )

    [2] => Array
        (
            [id] => 2
        )

)

Note that if you have a value in $arr that is not on the $order list, you will need additional checks since the array_search function returns FALSE for undefined indexes.
up
2
chris at candm dot org dot uk
5 years ago
In case anyone is interested, comparative timings over 100000000 runs
Based on comparing integers (500 and 501)
Spaceship:4
()?: operator:10
Subtraction:2

Based on comparing floats (500.1 and 501.3) (caveats noted)
Spaceship:5
()?: operator:9
Subtraction:3

Based on comparing strings ("five" and "four")
Spaceship:7
()?: operator:17
(Subtraction obviously not available)

Note: a dummy run was done with an empty loop and the elapsed time for this was subtracted from each of the above times so that they reflect ONLY the time to do the comparisons. As for significance. unless you are doing very large numbers of comparisons where spaceships are the order of the day, the difference is insignificant.
up
4
inigo dot grimbergen at gmail dot com
7 years ago
to sort with numeric and empty values  and have the smallest on top:
<?php
    usort
($list, function($a, $b) {
        if(
$a == null && $b != null ) return 1;
        if(
$a != null && $b == null ) return -1;
        return
$a > $b ? 1 : -1;
    });
?>
returns
1
2
3
null
null
null
up
3
andi_mclean at ntlworld dot com
12 years ago
I needed a sort method that would sort strings but take note of any numbers and would compare them as number. I also want to ignore any non alphanumerical characters.

Eg.
Slot 1 Example
Slot 10 Example
Slot 2 Example

Should infact be
Slot 1 Example
Slot 2 Example
Slot 10 Example

<?php
function sort_with_numbers($a , $b) {
   
$a = explode(' ',$a);
   
$b = explode(' ',$b);
   
$size = min(count($a), count($b));
    for(
$index =0; $index < $size; ++$index) {
       
$a1 = ereg_replace("[^A-Za-z0-9]", "",$a[$index]);
       
$b1 = ereg_replace("[^A-Za-z0-9]", "",$b[$index]);
       
$equal = 0;
        if (
is_numeric($a1) && is_numeric($b1)) {
           
$equal = $a1 - $b1;
        } else {
           
$equal = strcasecmp($a1,$b1);
        }
        if (
$equal < 0) {
            return -
1;
        }
        if (
$equal > 0) {
            return
1;
        }
    }
    return
count($a) - count($b);   
}
?>
up
3
bo at erichsen dot com
23 years ago
when using usort to refer to a function inside a class i have succesfully used:

<?php usort($myarray,array($this,"cmp")); ?>
To Top