¿Cómo eliminar un objeto de la matriz?

4 minutos de lectura

avatar de usuario de johnlemon
juanlemon

¿Cuál es una forma elegante de eliminar un objeto de una matriz de objetos en 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
  }  
  
}

Avatar de usuario de Gordon
gordon

Tu puedes hacer

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

También puedes usar spl_object_hash para crear un hash para los objetos y usarlo como clave de matriz.

Sin embargo, PHP también tiene una estructura de datos nativa para 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 Traversableasí que puedes foreach sobre eso también.

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

  • +1 ese es el mejor enfoque. Sin mencionar que a partir de PHP 5.3, SplObjectStorage implementos ArrayAccess.

    – Ionus G. Stan

    26 de agosto de 2010 a las 8:56

  • Dada la naturaleza de la pregunta, piense si search_array() devoluciones falselo mejor que se puede hacer es throw new OutOfBoundsException("No matching Observer found attached to the subject."). Cuando se considera cuidadosamente, sería una situación excepcional para un adjunto Observer para no existir mas! 🙂

    –Anthony Rutledge

    11 de febrero de 2021 a las 2:00


avatar de usuario de icio
icio

Estoy de acuerdo con las respuestas anteriores, pero en aras de la exhaustividad (donde es posible que no tenga ID únicos para usar como clave), mis métodos preferidos para eliminar valores de una matriz son los 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;
    });
}

Los cuales 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'));

Avatar de usuario de Cody Snider
cody snider

Recomiendo usar la ID (si tiene una, cualquier cosa que sea única para ese objeto debería funcionar dentro de lo razonable) del objeto como clave de matriz. De esta manera, 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]);

ACTUALIZAR:

class Data{

  private $arrObservers;

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

}

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

    – Cody Snider

    26 de agosto de 2010 a las 8:49

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

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

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

    – Mikulas Dite

    27 de agosto de 2010 a las 8:58

Para quitar un objeto de un multi dimensional array puedes usar esto:

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

Con array_column puede especificar el nombre de su columna clave:

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

Y esto eliminará el objeto indicado.

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

    – Mikulas Dite

    27 de agosto de 2010 a las 8:58

avatar de usuario de thinice
hielo delgado

Use esto para su almacenamiento interno de objetos en su lugar: http://us2.php.net/manual/en/class.splobjectstorage.php

¿Ha sido útil esta solución?