PHP:从数组中删除对象

时间:2010-08-26 08:24:52

标签: php arrays object

从PHP中的对象数组中删除对象的优雅方法是什么?

只是要明确......

class Data{

  private $arrObservers;

  public add(Observer $o) {  
    array_push($this->arrObservers, $o);  
  }    
  public remove(Observer $o) {  
    // I NEED THIS CODE to remove $o from $this->arrObservers
  }  

}

12 个答案:

答案 0 :(得分:46)

你可以做到

function unsetValue(array $array, $value, $strict = TRUE)
{
    if(($key = array_search($value, $array, $strict)) !== FALSE) {
        unset($array[$key]);
    }
    return $array;
}

您还可以使用spl_object_hash为对象创建哈希并将其用作数组键。

但是,PHP还有一个带有SplObjectStorage的对象集合的本机数据结构:

$a = new StdClass; $a->id = 1;
$b = new StdClass; $b->id = 2;
$c = new StdClass; $c->id = 3;

$storage = new SplObjectStorage;
$storage->attach($a);
$storage->attach($b);
$storage->attach($c);
echo $storage->count(); // 3

// trying to attach same object again
$storage->attach($c);
echo $storage->count(); // still 3

var_dump( $storage->contains($b) ); // TRUE
$storage->detach($b);
var_dump( $storage->contains($b) ); // FALSE

SplObjectStorageTraversable,因此您也可以foreach覆盖它。

在旁注中,PHP还具有SubjectObserver的原生接口。

答案 1 :(得分:14)

我同意上面的答案,但为了完整起见(你可能没有唯一的ID用作键)我从数组中删除值的首选方法如下:

/**
 * Remove each instance of a value within an array
 * @param array $array
 * @param mixed $value
 * @return array
 */
function array_remove(&$array, $value)
{
    return array_filter($array, function($a) use($value) {
        return $a !== $value;
    });
}

/**
 * Remove each instance of an object within an array (matched on a given property, $prop)
 * @param array $array
 * @param mixed $value
 * @param string $prop
 * @return array
 */
function array_remove_object(&$array, $value, $prop)
{
    return array_filter($array, function($a) use($value, $prop) {
        return $a->$prop !== $value;
    });
}

以下列方式使用:

$values = array(
    1, 2, 5, 3, 5, 6, 7, 1, 2, 4, 5, 6, 6, 8, 8,
);
print_r(array_remove($values, 6));

class Obj {
    public $id;
    public function __construct($id) {
        $this->id = $id;
    }
}
$objects = array(
    new Obj(1), new Obj(2), new Obj(4), new Obj(3), new Obj(6), new Obj(4), new Obj(3), new Obj(1), new Obj(5),
);
print_r(array_remove_object($objects, 1, 'id'));

希望有所帮助。

答案 2 :(得分:6)

我建议使用该对象的ID(如果有的话,该对象的唯一内容应该在合理范围内工作)作为数组键。这样,您可以在数组中寻址对象,而无需运行循环或将ID存储在另一个位置。代码看起来像这样:

$obj_array[$obj1->getId()] = $obj1;
$obj_array[$obj2->getId()] = $obj2;
$obj_array[$obj3->getId()] = $obj3;

unset($obj_array[$object_id]);

更新:

class Data{

  private $arrObservers;

  public add(Observer $o) {  
    $this->arrObservers[$o->getId()] = $o;  
  }    
  public remove(Observer $o) {  
    unset($this->arrObservers[$o->getId()]);
  }  

}

答案 3 :(得分:3)

unset($myArray[$index]);其中$index是您要删除的元素的索引。如果您不是更具体的答案,请显示一些代码或描述您想要做的事情。

答案 4 :(得分:3)

$obj_array['obj1'] = $obj1;
$obj_array['obj2'] = $obj2;
$obj_array['obj3'] = $obj3;
unset($obj_array['obj3']);

答案 5 :(得分:0)

答案 6 :(得分:0)

 function obj_array_clean ($array, $objId)
 {
    $new = array() ;
    foreach($array as $value)
    {
        $new[$value->{$objId}] = $value;
    }
    $array = array_values($new);
    return $array;
 }

 $ext2 = obj_array_clean($ext, 'OnjId');
  • 它将从数组对象$ array。
  • 中删除重复对象“OnjId”

答案 7 :(得分:0)

要从multi dimensional array中删除对象,您可以使用此功能:

$exampleArray= [
    [
      "myKey"=>"This is my key",
      "myValue"=>"10"
    ],
    [
      "myKey"=>"Oh!",
      "myValue"=>"11"
    ]
];

使用array_column,您可以指定密钥列名称:

if(($key = array_search("Oh!", array_column($exampleArray, 'myKey'))) !== false) {
    unset($exampleArray[$key]);
}

这将删除指示的对象。

答案 8 :(得分:0)

如果要从对象数组中删除一个或多个对象(使用spl_object_hash确定对象是否相同),可以使用此方法:

$this->arrObservers = Arr::diffObjects($this->arrObservers, [$o]);

来自this library

答案 9 :(得分:0)

阅读 GoF 书中的观察者模式部分?这是一个解决方案,它无需进行昂贵的搜索来查找要删除的对象的索引。

public function addObserver(string $aspect, string $viewIndex, Observer $view)
{   
    $this->observers[$aspect][$viewIndex] = $view;
}

public function removeObserver(string $aspect, string $viewIndex)
{
    if (!isset($this->observers[$aspect])) {
        throw new OutOfBoundsException("No such aspect ({$aspect}) of this Model exists: " . __CLASS__);
    }
    
    if (!isset($this->observers[$aspect][$viewIndex])) {
        throw new OutOfBoundsException("No such View for ({$viewIndex}) was added to the aspect ({$aspect}) of this Model:" . __CLASS__);
    }

    unset($this->observers[$aspect][$viewIndex]);
}

如果您不使用这种方式来跟踪哪些 Views 由特定的 Models 更新,您可以放宽“方面”维度。

public function addObserver(string $viewIndex, Observer $view)
{   
    $this->observers[$viewIndex] = $view;
}

public function removeObserver(string $viewIndex)
{   
    if (!isset($this->observers[$viewIndex])) {
        throw new OutOfBoundsException("No such View for ({$viewIndex}) was added to this Model:" . __CLASS__);
    }

    unset($this->observers[$viewIndex]);
}

总结

在将对象分配给数组之前以某种方式构建以查找元素。否则,您必须首先发现对象元素的索引。

如果您有大量的对象元素(或者甚至不止几个),那么您可能需要首先查找对象的索引。 PHP 函数 array_search() 是一种以值开头并返回索引/键的方法。

https://www.php.net/manual/en/function.array-search.php

请务必在调用函数时使用 strict 参数。

<块引用>

如果第三个参数strict设置为true,那么array_search() 函数将在 haystack 中搜索相同的元素。这 意味着它还将对针进行严格的类型比较 干草堆,和对象必须是同一个实例

答案 10 :(得分:-1)

试试这个,会解决你的问题。

class Data{
  private $arrObservers;

  public add(Observer $o) {  
    array_push($this->arrObservers,$o);  
  }    

  public remove($Observer $o) {  
    unset($this->arrObservers[$o]);  
  }  
}

答案 11 :(得分:-2)

我相信这是最好的方式

$index = array_search($o, $this->arrObservers, true);

unset($this->arrObservers[$index]);