2010-08-26 9 views
23

Qu'est-ce qu'un moyen élégant de supprimer un objet d'un tableau d'objets en PHP?PHP: Supprimer un objet du tableau

Juste pour être clair ..

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

Je suppose que vous voulez dire 'array_push ($ this-> arrObservers, $ o)'? – deceze

Répondre

37

Vous pouvez faire

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

Vous pouvez également utiliser spl_object_hash pour créer un hachage pour les objets et l'utiliser comme clé de tableau.

Cependant, PHP dispose également d'une structure de données native pour les collections d'objets avec 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 est Traversable, vous pouvez donc foreach dessus aussi bien.

Sur un sidenote, PHP a également des interfaces natives pour Subject et Observer.

+3

+1 c'est la meilleure approche. Sans oublier que depuis PHP 5.3, 'SplObjectStorage' implémente' ArrayAccess'. –

+1

Je suggère d'utiliser 'si (($ key = array_search ($ valeur, $ tableau, $ strict))! == false)' cuz '0 == false' – Anpher

+0

@Anpher bon appel. Fixé. Bien que je pense vraiment que l'OP devrait utiliser SplObjectStorage s'il n'y a que des objets à gérer. – Gordon

3

unset($myArray[$index]);$index est l'indice de l'élément que vous souhaitez supprimer. Si vous ne voulez pas de réponse plus spécifique, montrez du code ou décrivez ce que vous essayez de faire.

+0

C'est correct, mais comment trouver l'index d'un objet? Recherche par valeurs dans le tableau? – danidacar

+0

@daniphp Vous pouvez comparer des objets avec ===. –

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

-1 car OP donne un objet à la fonction, pas à la clé et par conséquent cet exemple est incomplet. –

6

Je recommande d'utiliser l'ID (si vous en avez un, tout ce qui sera unique à cet objet devrait fonctionner dans la raison) de l'objet comme la clé du tableau. De cette façon, vous pouvez adresser l'objet dans le tableau sans avoir à parcourir une boucle ou à stocker l'ID dans un autre emplacement. Le code ressemblerait à quelque chose comme ceci:

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

unset($obj_array[$object_id]); 

MISE À JOUR:

class Data{ 

    private $arrObservers; 

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

} 
+1

Cependant, vous aurez besoin d'une méthode getId() pour l'objet Observer. –

13

Je suis d'accord avec les réponses ci-dessus, mais par souci d'exhaustivité (où vous ne pouvez pas avoir des identifiants uniques à utiliser comme une clé) mes méthodes préférées d'éliminer les valeurs d'un tableau sont les suivantes:

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

qui sont utilisés de la façon suivante:

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

espoir qui aide.

-2

Je crois que c'est la meilleure façon

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

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

Essayez ceci, résoudra votre problème.

class Data{ 
    private $arrObservers; 

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

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

array_push assignera une clé numérique, donc vous ne trouverez pas $ o comme clé, même si les tableaux peuvent utiliser des objets pour les clés – 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'); 
  • Il supprime l'objet en double "OnjId" de tableau objets $ tableau.
1

Pour supprimer un objet d'un multi dimensional array vous pouvez utiliser ceci:

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

Avec array_column vous pouvez spécifier votre nom de colonne clé:

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

Et cela supprimera l'objet indiqué.