2010-09-20 114 views
7

我有一個數組充滿了來自同一類的對象。我想通過可選對象字段對此數組進行排序,例如$case->ID$case->Sender用於排序對象數組的PHP排序函數

是否有內置的array_sort()函數的味道,它已經這樣做了,還是我必須自己寫這個排序函數?

回答沒有詳細解釋 - 這更像是/否問題

感謝


我在usort失敗的嘗試:

function sortBy($sort) 
    { 
    usort($this->abuseCases, function($a, $b) { 
    if($a->{$sort} > $b->{$sort}) return 1; 
    if($a->{$sort} < $b->{$sort}) return -1; 
    else return 0; 
    }); 
    } 

另一次失敗的嘗試:

function sortBy($sort) 
    { 
     $this->sortBy = $sort; 

     usort($this->abuseCases, array("this", "srt")); 
    } 

    private function srt($a, $b) 
    { 
     if($a->{$this->sortBy} > $b->{$this->sortBy}) return 1; 
     if($a->{$this->sortBy} < $b->{$this->sortBy}) return -1; 
     else return 0; 
    } 

編輯凸點

+0

它爲什麼失敗?你看到了什麼結果? – codaddict 2010-09-20 07:09:40

+0

在第一次嘗試中,顯然找不到$ sort。在第二次嘗試中,我不知道如何引用函數'srt'。 – Hubro 2010-09-20 07:19:11

回答

10

您不僅可以使用匿名函數,還可以使用閉包,

function ($a,$b) use ($sort) { ... } 

$ sort將在函數體中可用。 自足例如:

<?php 
function getFn($sort) { 
    return function($a, $b) use($sort) { 
    if($a->$sort > $b->$sort) return 1; 
    if($a->$sort < $b->$sort) return -1; 
    return 0; 
    }; 
} 

$abuseCases = array(
    (object)array('ID'=>1, 'Sender'=>'Sender A'), 
    (object)array('ID'=>3, 'Sender'=>'Sender D'), 
    (object)array('ID'=>2, 'Sender'=>'Sender C'), 
    (object)array('ID'=>4, 'Sender'=>'Sender B') 
); 

echo "\n----- Sort By Sender ----\n"; 
usort($abuseCases, getFn('Sender')); 
foo($abuseCases); 

echo "\n----- Sort By ID ----\n"; 
usort($abuseCases, getFn('ID')); 
foo($abuseCases); 

function foo($a) { 
    foreach($a as $o) { 
    echo $o->ID, ' ', $o->Sender, "\n"; 
    } 
} 

打印

----- Sort By Sender ---- 
1 Sender A 
4 Sender B 
2 Sender C 
3 Sender D 

----- Sort By ID ---- 
1 Sender A 
2 Sender C 
3 Sender D 
4 Sender B 

更新:用PHP < 5.3你可以使用一個對象,而不是一個匿名函數。我們希望第二個參數是callable。這可以是php 5.3中的一個浮動函數,但它也可以是一個函數的名稱....或者一個對象和一個方法名稱,如array($obj, 'methodName')那樣傳遞。

$abuseCases = getData(); 
echo "\n----- Sort By Sender ----\n"; 
usort($abuseCases, array(new Foo('Sender'), 'compare')); 
foo($abuseCases); 

echo "\n----- Sort By ID ----\n"; 
usort($abuseCases, array(new Foo('ID'), 'compare')); 
foo($abuseCases); 

class Foo { 
    public $propName; // protected? 
    public function __construct($propertyName) { 
    $this->propName = $propertyName; 
    } 
    public function compare($a, $b) { 
    $prop = $this->propName; 
    if($a->$prop > $b->$prop) return 1; 
    if($a->$prop < $b->$prop) return -1; 
    return 0; 
    } 
} 

function foo($a) { 
    foreach($a as $o) { 
    echo $o->ID, ' ', $o->Sender, "\n"; 
    } 
} 
function getData() { 
    return array(
    (object)array('ID'=>1, 'Sender'=>'Sender A'), 
    (object)array('ID'=>3, 'Sender'=>'Sender D'), 
    (object)array('ID'=>2, 'Sender'=>'Sender C'), 
    (object)array('ID'=>4, 'Sender'=>'Sender B') 
); 
} 

(如果你大量使用的這一點 - 或者不想寫這樣一個-_-藉口 - 你可能希望定義一個接口一樣interface Comparator { ... },讓富實現該接口,並且有一定的功能/使用比較器的類,即usort()周圍的對象的包裝器。)

+2

關閉使用的一個很好的例子。僅適用於PHP 5.3+ – Iacopo 2010-09-20 07:26:32

+0

完美工作。謝謝!如果有一個需要更少代碼的相同結果的版本,我也很想看到:P – Hubro 2010-09-20 07:40:54

+0

對不起,PHP 5.3不會可用 - 我需要另一個解決方案 – Hubro 2010-09-23 20:34:03

7

您可以使用usort爲:

function cmp($a, $b) {  
    return ($a->ID - $b->ID); // assuming numeric ID 
} 

usort($arrayOfObjects,'cmp'); 

在PHP> = 5.3,你也可以使用匿名函數爲:

usort($arrayOfObjects, function($a, $b) { 
     return $a->ID - $b->ID; 
    }); 
+0

感謝您的回覆。你知道任何獲取預定義變量的方法嗎?我的嘗試失敗了(我已將它編輯到主文章中) – Hubro 2010-09-20 07:04:47

0

您將有寫它,但它是非常微不足道的usort()

function my_obj_sort($a, $b) { 
    return strnatcasecmp($a->Sender, $b->Sender); 
} 

usort($cases, 'my_obj_sort'); 
0

你應該看看usort()函數。它接受自定義排序的回調,這就是你想要的。

0

從設計POV中,更好的選擇是使用專用對象(如CasesCollection)而不是普通數組。您可以使排序鍵成爲此對象的成員,並在排序回調中簡單地將其稱爲$this->sortKey