从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
}
}
答案 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
SplObjectStorage
为Traversable
,因此您也可以foreach
覆盖它。
答案 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');
答案 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]);