2015-06-16 3 views
5

Ich mag den funktionalen Programmierstil der Verwendung von Array-Map, um ein Array von Objekten aus einem anderen Array von Objekten zu erstellen.Kann ich die Schlüssel eines Arrays mit Array-Funktionen wie array_map

$newObjects = array_map(
    function($oldObject) { 
    return new NewObject($oldObject); 
    }, 
    $oldObjects 
); 

Welche alles funktioniert gut, aber ich würde wirklich in der Lage sein wie die Indizes des Arrays zu setzen, so dass sie die IDs der ursprünglichen Objekte für eine einfachere Suche und den Abruf aus dem Array sind, aber ich kann nicht glauben, wie man mach es anders als das, was nicht so elegant ist.

$newObjects = array(); 
foreach ($oldObjects as $oldObject) { 
    $newObjects[$oldObject->getId()] = new NewObject($oldObject); 
} 

Gibt es eine Möglichkeit, das kann ich tun?

+0

Devil's Advocate Kommentar: so viel wie ich liebe Karte/reduzieren/zu Fuß usw. manchmal eine 'foreach' ist die einfachste, lesbare Lösung :) –

+0

Ja, ich stimme, Pferde für Kurse und all das. Mit Blick auf den Vorschlag unten hat die Foreach viel mehr in Bezug auf Stil und Lesbarkeit –

Antwort

1

Was ist, wenn Sie array_walk und ein temporäres Array mit Ihren neuen Indizes verwenden.

$array = ['A', 'B', 'C', 'D']; 
    $reIndexedTemp = []; 

    array_walk(
     $array, 
     function ($item, $key) use (&$reIndexedTemp) { 
      // here you can have your logic to assemble your new index 
      $reIndexedTemp[$key + 100] = $item; 
     } 
    ); 

    //$array = $reIndexedTemp; 

    var_dump($array, $reIndexedTemp); 

Ausgang (ohne die Kommentarzeile):

array(4) { 
    [0] => 
    string(1) "A" 
    [1] => 
    string(1) "B" 
    [2] => 
    string(1) "C" 
    [3] => 
    string(1) "D" 
} 
array(4) { 
    [100] => 
    string(1) "A" 
    [101] => 
    string(1) "B" 
    [102] => 
    string(1) "C" 
    [103] => 
    string(1) "D" 
} 
+0

Hmm, ich denke, das ist weniger elegant! Ich wollte kein temporäres Array verwenden. Auch der Schlüssel $ ist nur der ursprüngliche Schlüssel, der nicht wichtig ist, um ehrlich zu sein. –

+0

Ich bin kein Fan des Temp-Arrays :), aber all diese Array-Funktionen, die ich mir vorstellen kann, sind aus den offensichtlichen Gründen auf die Array-Indizes zurückzuführen. Und das Manipulieren einer Mitte einer Verarbeitung des Arrays selbst scheint keine gute Idee zu sein. Wenn Sie den Schlüssel aus dem ursprünglichen Array überhaupt nicht benötigen, können Sie die Methode array_walk ignorieren und die array_map behalten, aber ich fürchte, das temporäre Array wird weiterhin benötigt! – Ali

+1

Es ist kein temporäres Array. Es speichert die Ausgabe, die Sie benötigen. Leider modifiziert 'array_walk()' das Array, das es als Argument erhält und gibt keinen nützlichen Wert zurück.Es kann nicht direkt in einem funktionalen Programmierstil verwendet werden :-(Wenn Sie diesen Verarbeitungsfluss an mehreren Stellen verwenden müssen, denken Sie daran, den obigen Code in eine Funktion einzufügen, die das "temporäre" Array zurückgibt (und Ihren Wunsch nach funktionalem Programmierstil erfüllt).) – axiac

0

Umsah - Looking for array_map equivalent to work on keys in associative arrays

Schlägt es array_combine mit funktionieren könnte

Also ich denke, es wäre

sein
$newObjects = array_combine(
    array_map(
    function($oldObject) { 
     return $oldObject->getId(); 
    }, 
    $oldObjects 
), 
    array_map(
    function($oldObject) { 
     return new NewObject($oldObject); 
    }, 
    $oldObjects 
) 
); 
wahrscheinlich

Hmm das Beste, gerade diese Seite von overblown aber auf jeden Fall viel komplexer als die foreach

+0

Snap! Sort of ... Ich habe gerade Ihren Beitrag gesehen, nachdem ich meinen eingereicht habe –

1

denke ich, ein foreach ist wahrscheinlich die am besten lesen Lösung in diesem Fall, aber Sie können array_map() mit array_combine() verwenden, um zu erreichen, was Sie wollen. Etwas wie:

// empty array to store the old object ids 
$ids = []; 

// map over old objects, inheriting $id 
// from parent scope by reference 
$objs = array_map(function($oldObject) use (&$ids) { 
    $ids[] = $oldObject->getId(); 
    return new NewObject($oldObject); 
}, $oldObjects); 

// combine id and object arrays 
$newObjects = array_combine($ids, $objs); 

this helps :)

+0

Ah ja, das ist ein bisschen sauberer als meins. Obwohl ich aus irgendeinem Grund das externe Array nicht mag (ich habe eine irrationale Abneigung gegen Objekte, die durch Referenz weitergegeben wurden!) –

+0

Haha, fair genug! Es sieht ein bisschen gnarly in Ordnung. Mehr 'funktionale' Sprachen tun das gleiche viel transparenter. PHP ist nicht die schönste Sprache, die ich denke, aber wir lieben es immer noch ... richtig ?? –

2

Das heißt - array_reduce() ist genau das, was Sie brauchen:

class Bar 
{ 
     protected $id; 

     public function __construct($id) 
     { 
       $this->id = $id; 
     } 

     public function getId() 
     { 
       return $this->id; 
     } 
} 

class Foo 
{ 
     protected $bar; 

     public function __construct(Bar $bar) 
     { 
       $this->bar = $bar; 
     } 
} 

$oldObjects = [new Bar('x'), new Bar('y'), new Bar('z')]; 

$newObjects = array_reduce($oldObjects, function($current, Bar $obj) { 
     $current[$obj->getId()] = new Foo($obj); 
     return $current; 
}, []); 

Dies wird alles tun, an Ort und Stelle ohne Speicher zusätzlich zu verbringen Arrays wie für array_combine()

Allerdings würde ich vorschlagen, solche Konstrukte zu verwenden, wenn sie notwendig sind. Dies zu verwenden, nur weil es "besser aussieht", ist vielleicht keine gute Idee - da einfache Schleifen in den meisten Fällen einfach lesbarer sind.

+0

Hmm, interessant.Haben ein bisschen mehr in das, um richtig zu bekommen, wie es funktioniert (nie wirklich Array_reduce viel verwendet). Ich stimme ve Ich denke, dass entweder die foreach- oder die array_combine-Optionen die beste Balance oder Lesbarkeit und Eleganz bieten. Dies ist mehr eine Übung im Verständnis als fordern, einen funktionalen Ansatz zu finden, der besser als der foreach ist (obwohl es nett wäre) –

+0

Ganz unten kochen alle diese Optionen auf die Schleife, so mit diesem ist es möglich nur um es unter der Haube zu verstecken –

Verwandte Themen