Php 将对象集合限制为唯一集

Php 将对象集合限制为唯一集,php,activerecord,spl,Php,Activerecord,Spl,目前我有一个名为Collection的PHP类。它使用数组来保存一组唯一的对象。它们是唯一的,不是因为它们有不同的内存地址(尽管它们显然有),而是因为集合中没有等价的对象 我一直在阅读有关SplObjectStorage的文章,它比数组具有显著的速度优势,并且可能比我的集合类更易于维护。我的问题是,SplObjectStorage不关心等价性,只关心标识。例如: class Foo { public $id; function __construct($int){ $this-

目前我有一个名为
Collection
的PHP类。它使用数组来保存一组唯一的对象。它们是唯一的,不是因为它们有不同的内存地址(尽管它们显然有),而是因为集合中没有等价的对象

我一直在阅读有关
SplObjectStorage
的文章,它比数组具有显著的速度优势,并且可能比我的
集合
类更易于维护。我的问题是,
SplObjectStorage
不关心等价性,只关心标识。例如:

class Foo {
  public $id;

  function __construct($int){
    $this->id=$int;
  }

  function equals(self $obj){
    return $this->id==$obj->id;
  }
}

$f1a = new Foo(1);
$f1b = new Foo(1);//equivalent to $f1a
$f2a = new Foo(2);
$f2b = $f2a; //identical to $f2a

$s=new SplObjectStorage;
$s->attach($f1a);
$s->attach($f1b);//attaches (I don't want this)
$s->attach($f2a);
$s->attach($f2b);//does not attach (I want this)

foreach($s as $o) echo $o->id; //1 1 2, but I wish it would be 1 2
因此,我一直在考虑如何将
SplObjectStorage
子类化,使其
attach()
受到对象等价性的限制,但到目前为止,它涉及将对象的
$data
设置为“等价性签名”,这似乎需要在数据结构中循环,直到找到(或没有)匹配值

e、 g:


有更好的方法吗?

如果唯一定义相等的东西是相对于另一个对象的,那么我恐怕你想要的是不可能的。想想看,除非我检查每个对象,否则无法确定一个对象已经包含在数组中,因此无论发生什么情况,我的复杂性都是O(n)

但是,如果将等式设为绝对值,则这是可能的。为此,必须为每个对象生成一个哈希值。当且仅当两个对象的散列相等时,它们才会相等。一旦有了它,就可以用HashMap实现O(1)


在后台,这正是SplObjectStorage所做的,它将对象的地址作为其哈希值。

因此,基本上您需要一种基于唯一ID的单例。也许您应该获得一个内部带有数组的静态变量,并将ID为的对象存储为数组key@Tsadiq:这就是我在
收藏
类中所做的工作。但鉴于SplObjectStorage已被证明比同等阵列快得多,我正试图找出如何利用它。因此,您可能只需要在Foo中使用一个比较方法,该方法返回该ID并比较两个对象的ID:)如果实例化仅基于唯一ID,那么您不需要散列,只需要ID属性或比较method@Tsadiq. 你玩弄名字。“id属性”将是“哈希值”。
class MyFooStorage extends SplObjectStorage {

  function attach(Foo $obj){
    $es=$obj->id;
    foreach($this as $o=>$data) {//this is the inefficient bit
      if($es==$data) return;
    }
    parent::attach($obj);
    $this[$obj]=$es;
  }
}