2010-07-07 92 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