2014年5月8日 星期四

[PHP] usort()

這次要來討論 usort()。

我們假設以下情況依照水果名稱排序:

$fruits = array(
   array('id' => 1, 'name' => 'apple'),
   array('id' => 2, 'name' => 'orange'),
   array('id' => 3, 'name' => 'banana'),
   array('id' => 4, 'name' => 'banana'));

usort($fruits, function ($a, $b) {
   if ($a['name'] === $b['name']) { return 0; }
   return $a['name'] < $b['name'] ? -1 : 1;
});

/**
 * Output:
 * $fruits = array(
 *    array('id' => 1, 'name' => 'apple'),
 *    array('id' => 4, 'name' => 'banana'),
 *    array('id' => 3, 'name' => 'banana'),
 *    array('id' => 2, 'name' => 'orange'));
 */
結果似乎有點不符預期,banana (id=3) 不是出現在 banana (id=4) 前面。

再測試一次,這次改為回傳總是 0,即左右等值,所以預期順序應該不會有任何變化。 但是做完 usort() 之後,結果卻是幫我們進行一次反向排序。

usort($fruits, function ($a, $b) { return 0; });

/**
 * Expect:
 * $fruits = array(
 *    array('id' => 1, 'name' => 'apple'),
 *    array('id' => 2, 'name' => 'orange'),
 *    array('id' => 3, 'name' => 'banana'),
 *    array('id' => 4, 'name' => 'banana'));
 * Acutal:
 * $fruits = array(
 *    array('id' => 4, 'name' => 'banana'),
 *    array('id' => 3, 'name' => 'banana'),
 *    array('id' => 2, 'name' => 'orange'),
 *    array('id' => 1, 'name' => 'apple'));
 */

查閱 PHP Manual 之後, 發現到這段說明:

Note: If two members compare as equal, their relative order in the sorted array is undefined.
原來等值並沒有規定怎麼處理。

由於等值並沒有規範,所以我們需要再做一些判斷,才會是我們預期的結果。

usort($fruits, function ($a, $b) {
   if ($a['name'] === $b['name']) { return $a['id'] > $b['id']; }
   return $a['name'] < $b['name'] ? -1 : 1;
});

/**
 * Output:
 * $fruits = array(
 *    array('id' => 1, 'name' => 'apple'),
 *    array('id' => 3, 'name' => 'banana'),
 *    array('id' => 4, 'name' => 'banana'),
 *    array('id' => 2, 'name' => 'orange'));
 */

PHP 5.3.24 (cli) (built: Jun 10 2013 16:42:20)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies
    with Xdebug v2.2.0rc1, Copyright (c) 2002-2012, by Derick Rethans

沒有留言:

張貼留言

[Java] Invalid HTTP method: PATCH

最近系統需要使用 Netty4,所以把衝突的 Netty3 拆掉,然後就出現了例外。 pom.xml <dependency> <groupId>com.ning</groupId> <artifactId>as...