2010-07-07 97 views
3

我經常遇到一個場景,其中有兩個對象集合(數組或IteratorAggregate類),並且需要區分這兩個列表。PHP中對象的差異集合

通過DIFF,我的意思是:

  • 檢測重複的對象(邏輯,用於檢測重複將發生變化的情況下逐案)
  • 添加新對象
  • 刪除不在其他對象列表

本質上,我正在尋找類似array_diff的東西,與對象一起工作。到目前爲止,我一直在爲每種類型的集合反覆編寫相同的邏輯。顯然,由於重複對象的條件會因案例而異,因此沒有一個單獨的解決方案。但是,人們發現一種普通的模式或抽象是處理這種問題的一種優雅方式嗎?

+2

如果你需要抽象的合作如果每個對象都是一個類的實例,那麼你可以實現一個類特定的equals(obj)方法,它將抽象它的一半,然後剩下的就是迭代,看看什麼沒有改變,插入了什麼,什麼是已被刪除。 – nathan 2010-07-07 20:10:06

+0

@納森的建議很好。然而,爲了提高效率,你應該在'equals'函數中執行一致的'hashCode'函數,該函數爲對象提供一個哈希碼(一致意味着兩個相等的對象應該具有相同的哈希碼)。從Java的HashSet中獲取靈感(您可能希望查看HashMap的源代碼,因爲這是Java中的哈希集合,即removeAll和add操作)。 – Artefacto 2010-07-07 21:02:18

回答

2

spl_object_hash將幫助您確定兩個對象是否相同。

+1

我不知道,所以謝謝。問題是,我試圖比較來自ORM的對象,因此儘管對象可能在語義上相同,但它們在其屬性中都有唯一的ID,並且會產生不同的散列值。 – 2010-07-07 20:03:36

1

由於PHP5.2存在一個本機對象集合與SplObjectStorage

的SplObjectStorage類從對象到數據提供地圖或,通過忽略數據,對象集。這種雙重目的在很多情況下都很有用,涉及需要唯一標識對象的情況。

$obj1 = new StdClass; $obj1->prop = 1; 
$obj2 = new StdClass; $obj2->prop = 2; 
$obj3 = new StdClass; $obj3->prop = 3; 
$obj4 = new StdClass; $obj4->prop = 4; 
$obj5 = new StdClass; $obj5->prop = 5; 

$collection1 = new SplObjectStorage; 
$collection1->attach($obj1); 
$collection1->attach($obj2); 
$collection1->attach($obj3); 

$collection2 = new SplObjectStorage; 
$collection2->attach($obj3); 
$collection2->attach($obj4); 
$collection2->attach($obj5); 

SplObjectStorage實現可數,迭代器,Traversable的,串行化和ArrayAccess接口(自5.3),這樣就可以在其上作爲輕鬆地重複如在任何其他Traversable的。當它用作對象集時,同一對象不能在SplObjectStorage中出現兩次。您可以輕鬆地比較兩個集合具有以下功能:

function collection_diff(SplObjectStorage $c1, SplObjectStorage $c2) 
{ 
    $diff = new SplObjectStorage; 
    foreach($c1 as $o) { 
     if(!$c2->contains($o)) { 
      $diff->attach($o); 
     } 
    } 
    return $diff; 
} 

當然,你可以調整這個使用自定義比較。用法很簡單:

$diff = collection_diff($collection1, $collection2); 
var_dump($diff); // will contain $obj1 and $obj2 

延伸閱讀:

+0

很好的答案,謝謝所有的例子。最後,我只是用物體哈希去了。我一定會考慮開發一個更強大的解決方案。 – 2010-07-13 13:45:56