2010-08-26 23 views
23

¿Cuál es una forma elegante de eliminar un objeto de una matriz de objetos en PHP?PHP: Eliminar objeto de la matriz

Para que quede claro ..

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

Supongo que quiere decir 'array_push ($ this-> arrObservers, $ o)'? – deceze

Respuesta

37

Usted puede hacer

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

También puede utilizar spl_object_hash para crear un hash de los objetos y usar eso como tecla de matriz

Sin embargo, PHP también tiene una estructura de datos nativa para las colecciones de objetos con 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 es Traversable, por lo que puede foreach sobre él también.

En una nota al margen, PHP también tiene interfaces nativas para Subject y Observer.

+3

+1 ese es el mejor enfoque. Sin mencionar que a partir de PHP 5.3, 'SplObjectStorage' implementa' ArrayAccess'. –

+1

Sugeriría usar 'if (($ key = array_search ($ value, $ array, $ strict))!! == false)' cuz '0 == false' – Anpher

+0

@Anpher good call. Fijo. Aunque realmente creo que el OP debería usar SplObjectStorage si solo hay objetos para manejar. – Gordon

3

unset($myArray[$index]); donde $index es el índice del elemento que desea eliminar. Si no quiere una respuesta más específica, muestre algún código o describa lo que está tratando de hacer.

+0

Esto está bien, pero ¿cómo puedo encontrar el índice de un objeto? Buscar por valores en la matriz? – danidacar

+0

@daniphp Puede comparar objetos con ===. –

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

-1 porque OP da un objeto a la función, no la clave y por lo tanto este ejemplo está incompleto. –

6

recomiendo el uso de la identificación (si tiene uno, algo que será único para ese objeto debe trabajar dentro de lo razonable) del objeto como la clave de la matriz. De esta forma, puede abordar el objeto dentro de la matriz sin tener que ejecutar un bucle o almacenar la ID en otra ubicación. El código sería algo como esto:

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

unset($obj_array[$object_id]); 

ACTUALIZACIÓN:

class Data{ 

    private $arrObservers; 

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

} 
+1

Sin embargo, necesitará un método getId() para el objeto Observer. –

13

Estoy de acuerdo con las respuestas anteriores, pero en aras de la exhaustividad (donde puede que no tenga identificadores únicos para utilizar como una llave) mis métodos preferidos de la eliminación de los valores de una matriz son las siguientes:

/** 
* 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; 
    }); 
} 

que se utilizan de la siguiente manera:

$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')); 

Espero que ayude.

-2

Creo que esta es la mejor manera

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

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

Prueba de esto, va a resolver su problema.

class Data{ 
    private $arrObservers; 

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

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

array_push asignará una clave numérica, por lo que no encontraría $ o como clave, incluso si las matrices pudieran usar objetos para las claves – Gordon

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'); 
  • Se eliminará el objeto duplicado "OnjId" de gama objetos $ matriz.
1

Para eliminar un objeto de un multi dimensional array puede utilizar esto:

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

Con array_column puede especificar el nombre de la clave de la columna:

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

Y se eliminará el objeto indicado.

Cuestiones relacionadas