2010-08-26 12 views
23

Qual è un modo elegante per rimuovere un oggetto da una matrice di oggetti in PHP?PHP: Rimuovi oggetto dall'array

Giusto per essere chiari ..

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

Suppongo che intendiate 'array_push ($ this-> arrObservers, $ o)'? – deceze

risposta

37

Si può fare

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

È inoltre possibile utilizzare spl_object_hash per creare un hash per gli oggetti e di utilizzarlo come chiave di array.

Tuttavia, PHP ha anche una struttura dati nativo per le collezioni di oggetti 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 è Traversable, in modo da poter foreach su di esso pure.

Su un sidenote, PHP ha anche interfacce native per Subject e Observer.

+3

+1 è l'approccio migliore. Per non parlare del fatto che a partire da PHP 5.3, 'SplObjectStorage' implementa' ArrayAccess'. –

+1

Vorrei suggerire di usare 'if (($ chiave = array_search ($ valore, $ array, $ strict))! == false)' cuz '0 == false' – Anpher

+0

@Anpher buona chiamata. Fisso. Anche se penso davvero che l'OP dovrebbe usare SplObjectStorage se ci sono solo oggetti da gestire. – Gordon

3

unset($myArray[$index]); dove $index è l'indice dell'elemento che si desidera rimuovere. Se non vuoi una risposta più specifica, mostra un codice o descrivi cosa stai cercando di fare.

+0

Questo è ok, ma come faccio a trovare l'indice di un oggetto? Cerca per valori nell'array? – danidacar

+0

@daniphp È possibile confrontare gli oggetti con ===. –

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

-1 perché OP assegna oggetto alla funzione, non alla chiave e quindi questo esempio è incompleto. –

6

mi consiglia di utilizzare l'ID (se ne avete uno, tutto ciò che può essere unico a tale oggetto dovrebbe funzionare entro limiti ragionevoli) dell'oggetto come la chiave dell'array. In questo modo è possibile indirizzare l'oggetto all'interno dell'array senza dover eseguire un ciclo o memorizzare l'ID in un'altra posizione. Il codice dovrebbe essere simile a questa:

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

unset($obj_array[$object_id]); 

UPDATE:

class Data{ 

    private $arrObservers; 

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

} 
+1

Tuttavia, sarà necessario un metodo getId() per l'oggetto Observer. –

13

Sono d'accordo con le risposte di cui sopra, ma per ragioni di completezza (in cui non si può avere ID univoci da utilizzare come chiave) i miei metodi di rimozione dei valori da un array preferiti sono i seguenti:

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

che vengono utilizzati nel modo seguente:

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

Speranza che aiuta.

-2

Credo che questo sia il modo migliore

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

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

Prova questo, risolverà il vostro 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 assegnerà un tasto numerico, quindi non troverai $ o come chiave, anche se gli array potrebbero usare oggetti per le chiavi – 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'); 
  • Sarà rimuovere l'oggetto duplicato "OnjId" dalla gamma degli oggetti $ array.
1

Per rimuovere un oggetto da una multi dimensional array è possibile utilizzare questo:

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

Con array_column è possibile specificare il nome della colonna chiave:

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

E questo rimuoverà l'oggetto indicato.