X-Ray: Feld aus mehrdimensionalem Array als Index eines zweiten Arrays

Hallo!

Auf der Suche nach der Ursache für ein mir völlig unverständliches Verhalten meines PHP-Skripts frage ich mich nun, ob folgendes in PHP überhaupt möglich ist:

Ich habe zwei Zweidimensionale Arrays, etwa

  
$projekte = array(  
  'A' => array(  
    'Investition' => 100,  
    'Ertrag' => 120  
  ),  
  'B' => array(  
    'Investition' => 80,  
    'Ertrag' => 105  
  )  
);  
  
$reihenfolge = array(  
  array('A', 'B'),  
  array('B', 'A')  
);  

Nun verwende ich folgenden Code, um auf Elemente des ersten Arrays zuzugreifen:

  
$i = 1;  
$investition = $projekte[$reihenfolge[0][$i]]['Investition'];  

Wird $investition anschließend den Wert 80 enthalten, oder klappt das so nicht?

Schönen Gruß
Stefan

  1. Hi,

    Auf der Suche nach der Ursache für ein mir völlig unverständliches Verhalten meines PHP-Skripts frage ich mich nun, ob folgendes in PHP überhaupt möglich ist:

    ich sehe da kein Problem. Magst Du uns besagtes Verhalten näher beschreiben, oder willst Du selbst dem Problem auf die Spur kommen?

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Auf der Suche nach der Ursache für ein mir völlig unverständliches Verhalten meines PHP-Skripts frage ich mich nun, ob folgendes in PHP überhaupt möglich ist:

      ich sehe da kein Problem. Magst Du uns besagtes Verhalten näher beschreiben, oder willst Du selbst dem Problem auf die Spur kommen?

      Danke, das ist schonmal gut. Inzwischen habe ich das Problem weiter eingrenzen können, es scheint an einer ganz anderen Stelle zu liegen. Man betrachte folgenden Code:

        
      $projekte = array(  
        'A' => array(  
          'Investition' => 80,  
          'Ertrag' => 100  
        ),  
        'B' => array(  
          'Investition' => 50,  
          'Ertrag' => 75  
        ),  
        'C' => array(  
          'Investition' => 105,  
          'Ertrag' => 130  
        ),  
        'D' => array(  
          'Investition' => 70,  
          'Ertrag' => 95  
        )  
      );  
        
      // Renidte bestimmen  
      foreach ($projekte as $p => &$w) {  
        $w['Rendite'] = $w['Ertrag'] / $w['Investition'];  
        $renditen[$p] = $w['Rendite'];  
      }  
        
      // Projekte nach Rendite sortieren (absteigend)  
      array_multisort($renditen, SORT_DESC, $projekte);  
        
      // Sich ausschliessende Projekte festlegen  
      $ausschlussprojekt1 = 'B';  
      $ausschlussprojekt2 = 'C';  
        
      echo "Projekte:<br><pre>";  
      print_r($projekte);  
      echo "</pre>";  
        
      // Moegliche Portfolios bestimmen  
      foreach ($projekte as $p => $w) {  
        if ($p != $ausschlussprojekt1) {  
          $portfolios[0][] = $p;  
        }  
        if ($p != $ausschlussprojekt2) {  
          $portfolios[1][] = $p;  
        }  
      }  
        
      echo "<hr>Projekte #2:<br><pre>";  
      print_r($projekte);  
      echo "</pre><hr>";  
      
      

      Die Ausgabe dieses Scripts kann man sich hier ansehen:
      http://bfwtest.smk.biz/test_mehrd_array_foreach.php

      Der springende Punkt ist: Durch die letzte foreach-Schleife wird offensichtlich das Array $projekte verändert. Das Muster der Veränderung kann ich noch nicht nachvollziehen. In diesem Beispeil werden die Werte von Projekt D durch die von Projekt C ersetzt. Warum?

      Schöne Grüße,
      Stefan

      1. Hi,

        Der springende Punkt ist: Durch die letzte foreach-Schleife wird offensichtlich das Array $projekte verändert. Das Muster der Veränderung kann ich noch nicht nachvollziehen. In diesem Beispeil werden die Werte von Projekt D durch die von Projekt C ersetzt. Warum?

        weil $w eine Referenz ist. Siehe Referenzen und insbesondere die Unterseite "Referenzen aufheben".

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Der springende Punkt ist: Durch die letzte foreach-Schleife wird offensichtlich das Array $projekte verändert. Das Muster der Veränderung kann ich noch nicht nachvollziehen. In diesem Beispeil werden die Werte von Projekt D durch die von Projekt C ersetzt. Warum?

          weil $w eine Referenz ist. Siehe Referenzen und insbesondere die Unterseite "Referenzen aufheben".

          Top, herzlichen Dank! Ich war davon ausgegangen die Referenz würde mit dem Ende der Schleife automatisch aufgehoben.

          1. Moin!

            Der springende Punkt ist: Durch die letzte foreach-Schleife wird offensichtlich das Array $projekte verändert. Das Muster der Veränderung kann ich noch nicht nachvollziehen. In diesem Beispeil werden die Werte von Projekt D durch die von Projekt C ersetzt. Warum?

            weil $w eine Referenz ist. Siehe Referenzen und insbesondere die Unterseite "Referenzen aufheben".

            Top, herzlichen Dank! Ich war davon ausgegangen die Referenz würde mit dem Ende der Schleife automatisch aufgehoben.

            foreach arbeitet in PHP4 immer mit Kopien der Arrays. Das war mein Basiswissen, sollte es für jedermann sein.

            Das Manual gibt explizit an, dass erst seit PHP5 der tatsächliche Arraywert und nicht nur die Kopie bearbeitet werden kann, wenn man eine Referenz einsetzt. Dieser Einschub ist genau eine Textzeile und ein Codebeispiel (inklusive Kommentar, warum nach dem foreach das unset() steht) lang...

            ... zumindest in der englischen Version. Argl! Die deutsche Version hebt den Block mit dem "Kopie" und "seit PHP5 gehts auch direkt" zwar mit einem längeren Text und einem deutlicheren Rahmen hervor, aber unterschlägt aufs Schändlichste das unset() inklusive Kommentar.

            Ist jetzt Bug 46358.
             - Sven Rautenberg

            --
            "Love your nation - respect the others."
      2. echo $begrüßung;

        foreach ($projekte as $p => &$w) {
          $w['Rendite'] = $w['Ertrag'] / $w['Investition'];
          $renditen[$p] = $w['Rendite'];
        }

        An dieser Stelle legst du $w als Referenz an, um die Elemente von $projekte bearbeiten zu können. Nach Abschluss der Schleife bleibt $w als Referenz auf den Eintrag D bestehen. Weitere Schreibversuche auf $w ändern also auch den D-Eintrag.

        foreach ($projekte as $p => $w) {

        Ein solcher findet hier statt. Wenn du das $w mit unset() nach der ersten foreach-Schleife beseitigst, kannst du es anschließend als normale Variable wiederverwenden.

        print_r($projekte);

        Kontrollausgaben sind immer gut, mit var_dump() allerdings sieht man zusätzlich noch ein & als Hinweis auf die Referenz.

        echo "$verabschiedung $name";

  2. Moin!

    $i = 1;
    $investition = $projekte[$reihenfolge[0][$i]]['Investition'];

      
    Man kann jeden Multischritt auch in einzelnen Schritten vornehmen, um so nach und nach zum Ziel zu gelangen. Die Einzelschrittlösung lässt sich, da sie hauptsächlich aus Variablenkopiererei besteht, nach und nach (soweit das eigene Verständnis nachkommt) verdichten.  
      
    
    > Wird $investition anschließend den Wert 80 enthalten, oder klappt das so nicht?  
      
    Du hast eine Erwartung. Du hast Code. Das sind die besten Voraussetzungen, um durch einen simplen Testlauf zu prüfen, ob der Code die Erwartung erfüllt, oder inwieweit er davon abweicht. "Just do it!"  
      
     - Sven Rautenberg