PHP Array aufspalten anhand der Elemente

killray

Lt. Commander
Registriert
Jan. 2009
Beiträge
1.066
Hi, hab hier ein kleines Problem mit einem Skript bei dem ich mir schon einige Zeit den Kopf zerbreche. Und zwar lese ich ein CSV in PHP als Array ein und habe dann folgende Struktur:

Code:
Array
(
    [0] => Array
        (
            [Ort] => Musterstadt
            [Jahr] => 2011,000
            [Mon] => 1,000
        )

    [1] => Array
        (
            [Ort] => Musterstadt
            [Jahr] => 2011,000
            [Mon] => 2,000
        )

    [2] => Array
        (
            [Ort] => Musterstadt
            [Jahr] => 2011,000
            [Mon] => 3,000
        )

Dies möchte ich anhand des Ortes und Jahres in einzelne Arrays aufteilen um diese dann mittels JQuery zu visualisieren. dazu benutze ich folgendes Konstrukt:

PHP:
echo '<table>';
$i = 0;
while($i < count($data)) {
    if ($data[$i]['Ort'] == $data[$i+1]['Ort'] && $data[$i]['Jahr'] == $data[$i+1]['Jahr']) {
        echo '<tr>';
        echo '<td>' . $data[$i]['Ort'] . '</td>';
    } else {        
        echo '</tr>';  
        echo '</table><hr /><table>';            
    }    
    $i++; 
}
echo '</table>';

Leider habe ich folgende Probleme dabei:

1. Notice: Undefined offset: 244 in XXX, da I immer um eins zu weit läuft
2. Ich bekomme nie den ersten oder letzten Wert, je nachdem ob ich i+1 oder i-1 rechne.

Kann mir einer bei dem Problem helfen?
 
Irgendwas in die Richtung (komplett ungetestet):

PHP:
$last_ort = $data[0]['Ort'];
$last_jahr = $data[0]['Jahr'];

for($i = 0; $i < count($data); $i++) {
  if ($data[$i]['Ort'] != $last_ort || $data[$i]['Jahr'] != $last_jahr) {
    echo '</tr>';
    echo '</table><hr /><table>';
  }
  else {
    echo '<tr>';
    echo '<td>' . $data[$i]['Ort'] . '</td>';
  }

  $last_ort = $data[$i]['Ort'];
  $last_jahr = $data[$i]['Jahr'];
}
 
Zuletzt bearbeitet:
Das +1 und -1 rührt daher, dass ich in dem Array $data vergleichen möchte, ob der Ort oder das Jahr an der Stelle i gleich dem an der Stelle i+1 ist und an dieser Stelle aufspalten möchte, so dass ich am Ende bei folgenden Arrays lande:

Die Länge ist leider nicht fest, also die Anzahl der Monate variiert. Mit meinem Ansatz stoße ich aber immer wieder auf Probleme.

Code:
Ort            2012	1	94.38
Ort            2012	2	95.61
Ort            2012	3	95.66
Ort            2012	4	97.13
Ort            2012	5	97.11
Ort            2012	6	97.23
Ort            2012	7	97.01
Ort            2012	8	97.68
Ort            2012	9	96.2
Ort            2012	10	95.44
Ort            2012	11	95.92

Code:
Ort            2011	1	94.38
Ort            2011	2	95.61
Ort            2011	3	95.66
Ort            2011	4	97.13
Ort            2011	5	97.11
Ort            2011	6	97.23
Ort            2011	7	97.01
Ort            2011	8	97.68
Ort            2011	9	96.2
Ort            2011	10	95.44
Ort            2011	11	95.92
 
Zuletzt bearbeitet:
Warum baust du deine Datenstruktur dann nicht nach dem Muster $Daten[Ort][Jahr][Monat] = Preis auf? So fallen überflüssige Überprüfungen weg und es wird übersichtlicher. Außerdem geht somit das iterieren zehn mal einfacher.
 
Hmm, also ich bekomme eine feste CSV die wie folgt aufgebaut ist:

Code:
Ort;    Jahr;        Mon;  Sollzeit ;     Fehlzeit
Musterstadt;2011,000;1,000;79015,000;3996,97000

Das Format kann ich nicht ändern sondern muss damit arbeiten, macht es nicht gerade leichter, ich weiß ^^.

Mit folgendem Code lese ich das CSV in ein Array und sortiere es gleich nach Ort, Monat und Jahr:

PHP:
$handle = fopen("Mappe1.csv", "r");
$i = 0;
while (($line  = fgetcsv($handle, 1000, ";")) !== FALSE) {
    if($i == 0) {
        $c = 0;
        foreach($line as $col) {
            $cols[$c] = $col;
            $c++;
        }
    } else if($i > 0) {
        $c = 0;
        foreach($line as $col) {
            $data[$i][$cols[$c]] = $col;
            $c++;
        }
    }
    $i++;
}

# get a list of sort columns and their data to pass to array_multisort
$sort = array();
foreach($data as $k=>$v) {
    $sort['Ort'][$k] = $v['Ort'];
    $sort['Jahr'][$k] = $v['Jahr'];
    $sort['Mon'][$k] = $v['Mon'];
}
# sort by event_type desc and then title asc
array_multisort($sort['Ort'], SORT_ASC, $sort['Jahr'], SORT_NUMERIC, SORT_ASC, $sort['Mon'], SORT_NUMERIC, SORT_ASC, $data);

@bu1137 Dein Code unterschlägt ab dem zweiten Ort wieder den ersten Monat, aber immerhin ist jetzt der erste komplett drin ^^.
 
Aja...

PHP:
$last_ort = '';
$last_jahr ='';

for($i = 0; $i < count($data); $i++) {
  if ($data[$i]['Ort'] != $last_ort || $data[$i]['Jahr'] != $last_jahr) {
    if ($i > 0)
      echo '</table><hr />';
    echo '<table>';
  }

  echo '<tr><td>', $data[$i]['Ort'], "</td></tr>\n";

  $last_ort = $data[$i]['Ort'];
  $last_jahr = $data[$i]['Jahr'];
}
 
Du sollst auch nicht das Format der Datei ändern, sondern wie du mit den Daten umgehst.
Code:
<?php

$Data = array();

while( $row = fgetcsv( $handle, 0, ';' ) )
{
	$Ort = $row[$a];
	$Jahr = $row[$b];
	$Monat = $row[$c];
	$Preis = $row[$d];
	
	if( !isset( $Data[$Ort] ) ) $Data[$Ort] = array();
	if( !isset( $Data[$Ort][$Jahr] ) ) $Data[$Ort][$Jahr] = array();
	if( !isset( $Data[$Ort][$Jahr][$Monat] ) ) $Data[$Ort][$Jahr][$Monat] = -1;
	
	$Data[$Ort][$Jahr][$Monat] = $Preis;
}

ksort( $Data );
foreach( $Data as $Ort => $Data2 )
{
	sort( $Data[$Ort] );
	foreach( $Data2 as $Jahr => $Data3 )
		sort( $Data[$Ort][$Jahr] );
}

foreach( $Data as $Ort => $Data2 )
{
	// ort
	foreach( $Data2 as $Jahr => $Data3 )
	{
		// jahr
		foreach( $Data3 as $Monat => $Preis )
		{
			// monat + preis
		}
	}
}
Unvollständig und ungetestet. Du solltest dir evtl. nochmal die Sortierung ansehen. Schon hast du obiges Format und musst keinen überflüssigen Prüfungshickhack machen.
 
Danke erstmal für den Code. Mit gehts bei meinem Problem darum, dass ich eben für jeden Ort und Jahr jeweils getrennt etwas weiterverarbeiten möchte. Das heißt ich möchte die Daten aufteilen, es können 12 Monate Daten vorhanden sein oder auch nur 7 und die Anzahl der Orte ist ebenso variabel, sonst könnte ich es einfach mit array_chunk aufteilen.

Vielleicht wird das Problem so klarer, ich bin mit meiner Sortierung schon recht zufrieden, ich suche nur nach einer Möglichkeit mein Array so aufzuteilen oder auszugeben, dass er bei einem neuen Ort oder einem neuen Jahr von vorne anfängt und die Länge des jeweiligen Arrays variabel ist.
 

Ähnliche Themen

Zurück
Oben