【问题标题】:limiting a collection of objects to a unique set将对象集合限制为唯一集合
【发布时间】:2011-03-04 21:11:32
【问题描述】:

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

我一直在阅读有关 SplObjectStorage 的信息,它比数组具有显着的速度优势,并且可能比我的 Collection 类更容易维护。我的问题是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 设置为“等效签名”,这似乎需要遍历数据结构,直到我找到(或没有)匹配的值。

例如:

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;
  }
}

有没有更好的办法?

【问题讨论】:

  • 所以基本上你想要一种基于唯一 ID 的单例。也许你应该得到一个里面有一个数组的静态变量,并将你的 objetcs 存储为 ID 作为数组键
  • @Tsadiq:这基本上就是我对Collection 班级所做的事情。但鉴于 SplObjectStorage 已被证明比等效数组快得多,我正试图弄清楚如何利用它。 technosophos.com/content/…
  • 所以也许您只需要在您的 Foo 中使用一个比较方法来返回 ths ID 并比较您的两个对象的 ID :)

标签: php activerecord spl


【解决方案1】:

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

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

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

【讨论】:

  • 如果实例化仅基于唯一 ID,那么您不需要哈希,只需一个 id 属性或比较方法
  • @Tsadiq。你玩名字。 “id 属性”将是“哈希值”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 2015-09-24
  • 2021-09-24
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多