Array sortieren, und filtern.

Hallo,

Ich würde gerne Daten die in einem Array stehen nach Datum sortieren und Duplikate auch noch ausfiltern. Gibt es dafür einen Funktion, oder Skript.

Gruß Uwe

Wie sieht das array denn aus? Beispiel?

Hallo,

Array
Betreff,StartDatum,StartZeit,EndDatum,EndZeit
Weinachten,24.12.2010,18:00:00,24.12.2010,23:30:00

Ich würde dieses gerne Nach StartDatum,StartZeit sortieren, und Doppelteeinträge rausfiltern.

Gruß Uwe

Du willst ein Array nach Inhalten sortieren, das geht z.B. mit

sort

Doppelte Elemente kann man mit

unique

"rauskicken.

Die Funktionen für Arrays findest Du hier:
PHP: array - Manual

Allerdings habe ich, wie sysrun, noch das Problem, Dein Array genau zu erkennen, denn was Du aufgezeigthast ist ne Liste, di man in ganz unterschiedlicher Weise in einem Array abbilden kann.

Wenn Du das Array schon hast, dann nutze doch mal

print_r( $<name des arrays> )

und poste das Ergebnis mal hier. Wenn Du uns dann noch genauer verrätst, nach was genau Du sortieren willst und woranman die Dubletten erkennt, können wir Dir sicher besser helfen.

jwka

p.s.:
Ich habe auch etwas gebraucht, um mit Arrays richtig umgehen zu können in PHP. Da ist es wirklich am besten, sich mal ein paar Stunden Zeit zu nehmen und selber mal Arrays zu basteln und damit zu „jonglieren“, z.B. Unter-Arrays zu sortieren, Arrayteile „herauszukopieren“ etc.

Hallo,

der Ausdruck vom Array sieht so aus.


Array
(
    [0] => Geburtstag von Ernst,23.09.2011,,,,Ganztägig,Serie
    [1] => Geburtstag von Vinzenz,14.01.2011,,,,Ganztägig,Serie
    [2] => Geburtstag von Rolf ,10.07.2011,,,,Ganztägig,Serie
    [3] => Geburtstag von Uwe ,03.08.2011,,,,Ganztägig,Serie
    [4] => Geburtstag von Annett,21.04.2011,,,,Ganztägig,Serie
    [5] => Geburtstag von Corinna ,17.04.2011,,,,Ganztägig,Serie
    [6] => Geburtstag von Matina ,23.10.2011,,,,Ganztägig,Serie
    [7] => Geburtstag von Doreen ,22.06.2011,,,,Ganztägig,Serie
    [8] => Geburtstag Bastian ,07.03.2011,,,,Ganztägig,Serie
    [9] => Geburtstag von Josefa ,15.09.2011,,,,Ganztägig,Serie
    [10] => Geburtstag von Harald ,28.09.2011,,,,Ganztägig,Serie
    [11] => Geburtstag Farbian ,17.12.2010,,,,Ganztägig,Serie
    [12] => Geburtstag von Franz-27.08.2011,,,,Ganztägig,Serie
    [13] => Allerheiligen,01.11.2011,,,,Ganztägig,
    [14] => Christi Himmelfahrt,02.06.2011,,,,Ganztägig,
    [15] => Mariä Himmelfahrt,15.08.2011,,,,Ganztägig,
    [16] => 2. Weihnachtsfeiertag,26.12.2010,,,,Ganztägig,
    [17] => Weihnachtstag,25.12.2010,,,,Ganztägig,
    [18] => Fronleichnam,23.06.2011,,,,Ganztägig,
    [19] => Tag der Deutschen Einheit,03.10.2011,,,,Ganztägig,
    [20] => Buß- und Bettag (z.T.),16.11.2011,,,,Ganztägig,
    [21] => Ostersonntag,24.04.2011,,,,Ganztägig,
    [22] => Ostermontag,25.04.2011,,,,Ganztägig,
    [23] => Heilige Drei Könige,06.01.2011,,,,Ganztägig,
    [24] => Karfreitag,22.04.2011,,,,Ganztägig,
    [25] => Neujahrstag,01.01.2011,,,,Ganztägig,
    [26] => Reformationstag,31.10.2011,,,,Ganztägig,
    [27] => Pfingstmontag,13.06.2011,,,,Ganztägig,
    [28] => Pfingstsonntag,12.06.2011,,,,Ganztägig,
    [29] => Tag der Arbeit,01.05.2011,,,,Ganztägig,
    [30] => Geburtstag von Rex ,24.02.2011,,,,Ganztägig,Serie
    [31] => Geburtstag von Rene ,23.05.2011,,,,Ganztägig,Serie
    [32] => Steuererklärung !!,31.05.2011,,,,Ganztägig,Serie
    [33] => AQ Treffen,03.12.2010,19:30:00,03.12.2010,22:00:00,150 Minuten,
    [34] => ITS,20.05.2011,06:00:00,20.05.2011,06:30:00,30 Minuten,
    [35] => Dr. Regel,09.12.2010,17:00:00,09.12.2010,17:30:00,30 Minuten,
    [36] => Pfingstsonntag,12.06.2011,,,,Ganztägig,
    [37] => Reformationstag,31.10.2011,,,,Ganztägig, 
)


Ich würde gerne nach dem ersten Datum sotieren (Feld2) und Doppelt rausfiltern zb. ([37] [26])

Nicht falsch verstehen: Ich will Dir jetzt mal nicht das Script schreiben, denn nur mit Üben kriegt man Übung. Aber ich sag Dir mal, wie ich das machen würde:

1.) Rausschmeissen der Dubletten:
WENN (wie im Beispiel) Du sicher bist, dass Dubletten komplett übereinstimmen (denn Dein Array ist ein eindimensionales und die Werte sind vom Typ String, die Kommas sind normale Zeichen), kannst Du die mit unique() rauskicken. Wenn nicht, musst Du eine Schleife bauen … gleich.

2.) Um die Sortierung nach Datum (was ja genau genommen nicht reicht, weil es Einträge gibt, die dasselbe Datum haben --> wie weiter sortieren??) hinzukriegen musst Du „die Daten“ erstmal so umarbeiten, dass Du nach dem Datum sortieren kannst, d.h. Du musst das Datum aus dem String rausholen.

Das könnte in Deinem Falle (WENN dei Struktur der Zeilen zuverlässig immer in Form des ersten Werts vorliegt, also das Datum IMMER nach dem ersten Komma steht ===> Siehe Datensatz 12, da ist das nicht so!!!) am leichtesten so gehen:

2a. Mit einer Schleife (foreach) über alle Einträge des Arrays gehen, den Wert mittels expolde() selbst in ein Array verwandeln und das zweite Element (index-nr=1 !) herausnehmen.

Um das sortierbar zu machen, wendest Du darauf dann strtotime an, das gibt Dir einen numerischen Wert zurück, der Sekunden seit 01.011970 00:00:00 UTC entspricht.

2b. Diesen Wert speicherst Du in ein „Parallelarray“, dazu kannst Du den Key aus 2a nehmen.

Nun hast Du ein Array, welches Du (nach der Zeit) sortieren kannst. Tipp: Sort-Funktion, die die Index-Assoziation beibehält … Schritt 2c.

2e. Nun ne Schleife (foreach) über dieses sortierte Array laufen lassen und mit dem jweiligen Key einen Zugriff entweder auf die „Ur-Daten“ oder halt auf die vieleicht schon in Schritt 2a „angehübschten“ Daten.

Fertig.

Bei mir sind das so ca. 8-10 Zeilen (ohne „anhübschen“), je nach Formatierung.

Wenn Du noch Probleme hast, poste ich Dir auch den Code. Aber probier erstmal selber. Das Erfolgserlebnis ist dann viel größer.

jwka

Hallo jwka,

die Dubletten bin ich schon los, der Datensatz 12 ist falsch, da muß auch ein „,“ hin.

Was das sotieren betrieft da komme ich mit deinen Info garn nicht mehr klar, habe jetzt 2 Nächte schon probiert, aber irgendwie geht es nicht.

Ein Code als Hilfe wäre nicht schlecht.

Gruß Uwe

So weit bin ich. Und komm nicht weiter


foreach($termine_arr_komplett as $key => $value)     							
	{
	$value 			= str_replace('"',"",$value);       				
	$termine_array = explode(",", $value);

	$array_neu[$key] = strtotime($termine_array[1]);
	}

asort($array_neu);

foreach($array_neu as $key => $value)
	{

	}

Gruß Uwe

Beim Sortieren bietet PHP über PHP: usort - Manual die Möglichkeit, eine eigene Vergleichsfunktion zu definieren, durch die das Problem recht simpel wird:

<?php
$data = array("Geburtstag von Ernst,23.09.2011,,,,Ganztägig,Serie", "Geburtstag von Vinzenz,14.01.2011,,,,Ganztägig,Serie", "Geburtstag von Rolf ,10.07.2011,,,,Ganztägig,Serie", "Geburtstag von Uwe ,03.08.2011,,,,Ganztägig,Serie", "Geburtstag von Annett,21.04.2011,,,,Ganztägig,Serie", "Geburtstag von Corinna ,17.04.2011,,,,Ganztägig,Serie", "Geburtstag von Matina ,23.10.2011,,,,Ganztägig,Serie", "Geburtstag von Doreen ,22.06.2011,,,,Ganztägig,Serie", "Geburtstag Bastian ,07.03.2011,,,,Ganztägig,Serie", "Geburtstag von Josefa ,15.09.2011,,,,Ganztägig,Serie", "Geburtstag von Harald ,28.09.2011,,,,Ganztägig,Serie", "Geburtstag Farbian ,17.12.2010,,,,Ganztägig,Serie", "Geburtstag von Franz,27.08.2011,,,,Ganztägig,Serie", "Allerheiligen,01.11.2011,,,,Ganztägig,", "Christi Himmelfahrt,02.06.2011,,,,Ganztägig,", "Mariä Himmelfahrt,15.08.2011,,,,Ganztägig,", "2. Weihnachtsfeiertag,26.12.2010,,,,Ganztägig,", "Weihnachtstag,25.12.2010,,,,Ganztägig,", "Fronleichnam,23.06.2011,,,,Ganztägig,", "Tag der Deutschen Einheit,03.10.2011,,,,Ganztägig,", "Buß- und Bettag (z.T.),16.11.2011,,,,Ganztägig,", "Ostersonntag,24.04.2011,,,,Ganztägig,", "Ostermontag,25.04.2011,,,,Ganztägig,", "Heilige Drei Könige,06.01.2011,,,,Ganztägig,", "Karfreitag,22.04.2011,,,,Ganztägig,", "Neujahrstag,01.01.2011,,,,Ganztägig,", "Reformationstag,31.10.2011,,,,Ganztägig,", "Pfingstmontag,13.06.2011,,,,Ganztägig,", "Pfingstsonntag,12.06.2011,,,,Ganztägig,", "Tag der Arbeit,01.05.2011,,,,Ganztägig,", "Geburtstag von Rex ,24.02.2011,,,,Ganztägig,Serie", "Geburtstag von Rene ,23.05.2011,,,,Ganztägig,Serie", "Steuererklärung !!,31.05.2011,,,,Ganztägig,Serie", "AQ Treffen,03.12.2010,19:30:00,03.12.2010,22:00:00,150 Minuten,", "ITS,20.05.2011,06:00:00,20.05.2011,06:30:00,30 Minuten,", "Dr. Regel,09.12.2010,17:00:00,09.12.2010,17:30:00,30 Minuten,", "Pfingstsonntag,12.06.2011,,,,Ganztägig,", "Reformationstag,31.10.2011,,,,Ganztägig,");

$data = array_unique($data);
usort($data, 'compareEntries');
print_r($data);

function compareEntries ($a, $b)
{
    $a = explode(",", $a);
    $a = strtotime($a[1]);
    $b = explode(",", $b);
    $b = strtotime($b[1]);
    return ($a < $b) ? -1 : (($a == $b) ? 0 : 1);
}
?>

Danke Horst,

das geht, mal sehen ob ich das noch verstehe, was da abgeht.


    $a = explode(",", $a);
    $a = strtotime($a[1]);
    $b = explode(",", $b);
    $b = strtotime($b[1]);

$a[1] ist das Array,Stelle1 !

und was ist $b[1] ?

und ich bekomme (Undefined offset: 1 ) weil noch eine Leerzeile im Array ist.

Gruß Uwe

Hallo,

gibt es eine Möglichkeit ein Leerwert im Array zu löschen. Wie Datensatz [46]


   [45] => AQ Treffen,03.12.2010,19:30:00,03.12.2010,22:00:00,150 Minuten,,Uwe
    [46] => 

Gruß Uwe

Hallo Uwe,

kennst Du diese Site(s)?

http://www.php.net/manual/de/
Das ist Pflicht-Bookmark für mich als PHP Referenz

http://www.selfphp.info/
Da habe ich sehr oft Lösungen gefunden.

Zum Thema leere Indexelemente rauskicken (geht nicht immer damit, je nach Inhalten des Arrays, abe in Deinem Falle gehts):

array_filter( $array )
http://www.php.net/manual/de/function.array-filter.php
–> Falls die Funktion callback nicht angegeben wurde, werden alle Einträge des Arrays entfernt, die FALSE sind.

Um es micht zu spannend zu machen, hier mal ein paar Zeilen Code, die ich (in anderem Zusammenhang) für ein Tutorial zusammengestellt hab und an Deine Problematik kurz angepasst habe. War eigentlich für ne Messwert-Erfassung. Die Kommentare sollten eigentlich Erklärung genung sein, hoffe ich:


// DEFINE DATA --> SHOULD BE READ FROM FILE
	$data[0] = "Geburtstag von Heike,23.09.2010,,,,Ganztägig,Serie";
	$data[1] = "Termin,14.01.2010,19:30:00,,,Ganztägig,Serie";
	$data[2] = "Geburtstag von Rudolf ,10.07.2011,,,,Ganztägig,Serie";
	$data[3] = ""; // ABSICHTLICH EIN FALSCHER DATENSATZ
	$data[8] = "Geburtstag von Frank,27.08.2011,,,,Ganztägig,Serie";
	$data[10] = "Allerheiligen,01.11.2011,,,,Ganztägig,";
	$data[11] = "Christi Himmelfahrt,02.06.2011,,,,Ganztägig,";
	$data[12] = "Geburtstag von Else,27.08.2010,,,,Ganztägig,Serie";
	$data[13] = "Buß- und Bettag (z.T.),16.11.2011,,,,Ganztägig,";
	$data[14] = "Ostersonntag,24.04.2011,,,,Ganztägig,";
	$data[12] = "Ostermontag,25.04.2011,,,,Ganztägig,"; // ÜBERSCHREIBT ALTEN WERT VON 12 !!
	$data[21] = "Pfingstmontag,13.06.2011,,,,Ganztägig,";
	$data[22] = "Pfingstsonntag,12.06.2011,,,,Ganztägig,";
	$data[23] = "Tag der Arbeit,01.05.2011,,,,Ganztägig,";
	$data[24] = "Geburtstag von Arne ,25.05.2010,,,,Ganztägig,Serie"; // FRÜHERES DATUM WEITER HINTEN IN ARRAY
	$data[25] = "Steuererklärung !!,31.05.2011,,,,Ganztägig,Serie";
	$data[26] = "Pfingstsonntag,12.06.2011,,,,Ganztägig,";
	$data[30] = "Reformationstag,31.10.2011,,,,Ganztägig,"; // DOPPELT

// KILL DOUBLE ENTRIES
	$data = array_unique($data);

// KILL EMPTY ENTRIES
	$data = array_filter($data);

// REORDER ARRAY TO BE CONSISTENT
	// Achtung, dieses Vorgehen macht nicht immer Sinn ist aber,
	// bezüglich des Beispiels hier, zwingend nötig.
	sort($data);

// COLLECT & CONVERT DATA
	foreach( $data as $keyD => $valueD )
	{
		// Datensatz in Array umwandlen, um auf einzelne Werte zugreifen zu können
		// Ergebnis als Unterarray speichern --> 3-dimensionales Array
			$data2['values'][$keyD] = explode(",", $valueD);

		// "Parallelarray" für Sortierung nach Datum aufbauen
			$data2['timeAZ'][$keyD] = strtotime( $data2['values'][$keyD][1] );

		// "Parallelarray" für Sortierung nach Text aufbauen
			$data2['textAZ'][$keyD] = $data2['values'][$keyD][0];
			
		// "Parallelarray" für Sortierung nach Messwert aufbauen
			$data2['valAZ'][$keyD] = strtotime( $data2['values'][$keyD][4] );
	};

// SORT TO ORDER
	asort( $data2['timeAZ'] );
	asort( $data2['textAZ'] );
	//print_r( $data2 );
	//return("");


// FORMAT VALUES AND ADD HEADERS & FOOTERS

	$dotline = str_repeat( "-", 50);
	// FOR TIME-ORDERED TABLE
		$formate['timeAZ'] = "| %10.10s | %8.8s | %-30.30s | 
";
		$values['timeAZ'] =  "\$data2['values'][\$keyD][1],\$data2['values'][\$keyD][2], \$data2['values'][\$keyD][0]";
		$headers['timeAZ'][] = "          TIMETABLE BY DATE & TIME 
";
		$headers['timeAZ'][] = sprintf( $formate['timeAZ'], $dotline, $dotline, $dotline );
		$footers['timeAZ'][] = sprintf( $formate['timeAZ'], $dotline, $dotline, $dotline );
		$footers['timeAZ'][] = " Stand: " . date( "d.m.Y - H:i:s", time() ). "


" ;

	// FOR SUBJECT-ORDERED TABLE
		$formate['textAZ'] = "| %-30.30s | %10.10s | %8.8s |
";
		$values['textAZ'] = "\$data2['values'][\$keyD][0],\$data2['values'][\$keyD][1], \$data2['values'][\$keyD][2] ";
		$headers['textAZ'][] = "          TIMETABLE BY Subject 
";
		$headers['textAZ'][] = sprintf( $formate['textAZ'], $dotline, $dotline, $dotline );
		$footers['textAZ'][] = sprintf( $formate['textAZ'], $dotline, $dotline, $dotline );
		$footers['textAZ'][] = " Stand: " . date( "d.m.Y - H:i:s", time() ) . "


" ;

	// FOR VALUE-ORDERED TABLE
		$formate['valAZ'] = "| %6.3f | %10.10s | %8.8s | %-30.30s | 
";
		$formateHF['valAZ'] = "| %6.6s | %10.10s | %8.8s | %-30.30s | 
";
		$values['valAZ'] =  "\$data2['values'][\$keyD][4],\$data2['values'][\$keyD][1],\$data2['values'][\$keyD][2], \$data2['values'][\$keyD][0]";
		$headers['valAZ'][] = "          TIMETABLE BY DATE & TIME 
";
		$headers['valAZ'][] = sprintf( $formateHF['valAZ'], $dotline, $dotline, $dotline, $dotline );
		$footers['valAZ'][] = sprintf( $formateHF['valAZ'], $dotline, $dotline, $dotline, $dotline );
		$footers['valAZ'][] = " Stand: " . date( "d.m.Y - H:i:s", time() ). "


" ;

// OUTPOUT DATA FORMATTED
	foreach( $formate as $formatK => $formatV)
	{
		// PRINT HEADERS
				foreach( $headers[ $formatK ] as $key => $value)
				{
					echo $value;
				};

		// PRINT VALUES
				foreach( $data2[ $formatK ] as $keyD => $valueD)
				{
			//echo "key:" . $key . "
";

				   $scr = "printf( \$formatV ," . $values[$formatK] . ");";
				   //echo $scr ."
";
				   eval( $scr);
				};

		// PRINT FOOTERS
				foreach( $footers[ $formatK ] as $key => $value)
				{
					echo $value;
				};
	};




Ich habe auch den Eindruck, dass Deine Daten aus nem seriellen File gelesen werden. Kann das irgendwie ne Kalenderapp von hier sein? Dann kannst Du nämlich ein paar Schritte gleich beim Einlesen erledigen.
jwka

Hallo jwka ,

danke für die Info, die Daten kommen aus einem (VB-Skript) Export aus Outlook nach IPS.

siehe hier: http://www.ip-symcon.de/forum/f20/outlook-termine-anzeigen-11977/

Gruß Uwe

Die Daten aus dem seriellen File passen in ein 2-dimensionales Array:

Einlesen der Termine:


$termine=array(); // in dieses Array werden die Termine eingelesen

$file='c:/ordner/name.txt'; // Hier Pfad und Name der Datei einsetzen

$lines = file($file); // Hier wird in einem Rutsch die Datei in das Array $lines eingelesen
// $lines ist 1-dimensional und enthält jeweils eine Zeile, also einen Datensatz


foreach ($lines as $line_num => $line) {
    $felder=explode(',',$line); // Die Felder sind durch Kommas getrennt,
    // $felder enthält als eindimensionales Array die Spalten eines Datensatzes
    foreach ($felder as $feld_num => $feld) {
	$termine[$line_num][$feld_num]=trim($feld); // Das Array $termine wird geschrieben
    }
}
unset($felder); // freigeben des Speicherplates, da das Array nicht mehr gebraucht wird
unset($lines); // freigeben des Speicherplates, da das Array nicht mehr gebraucht wird

Sortieren von $termine:


$sortArray = array(); // Hilfsarray für das Sortieren nach einem bestimmten Feld
foreach($termine as $key => $array) { 
    $sortArray[$key] = $array[1]; // Index 0 würde nach dem ersten Feld Sortieren, Index 1 nach dem zweoten usw. 
} 
array_multisort($sortArray, SORT_DESC, SORT_NUMERIC, $termine); // Mulitsort sortiert ein zweites array mit ! 
unset($sortArray);// freigeben des Speicherplates, da das Array nicht mehr gebraucht wird
unset($array);// freigeben des Speicherplates, da das Array nicht mehr gebraucht wird

Da nach Datum sortiert werden soll, muß mann das ausgeschrieben Datum, z.B. „11.10.2010“ erst in einen
Timestamp ändern, sieht dann also so aus:


$sortArray = array(); // Hilfsarray für das Sortieren nach einem bestimmten Feld
foreach($termine as $key => $array) { 
  $a=$array[1]; // Index des Feldes, welches ein geschriebens Datum enthält
  $tag=intval(substr($a,0,2));
  $monat=intval(substr($a,3,2));
  $jahr=intval(substr($a,6,4));
  $ts=mktime(0,0,0,$monat,$tag,$jahr); // timestamp erzeugen
  $sortArray[$key] = $ts;
array_multisort($sortArray, SORT_DESC, SORT_NUMERIC, $termine); // Mulitsort sortiert ein zweites array mit ! 
unset($sortArray);// freigeben des Speicherplates, da das Array nicht mehr gebraucht wird
unset($array);// freigeben des Speicherplates, da das Array nicht mehr gebraucht wird


Hoffe, ich habe keine Flüchtigkeitsfehler gemacht. Bei mir funktionert so das Einlesen und Sortieren einer Datei, in der periodische Ereignisse zum Auslösen von Aktionen gespeichert sind.

PHP: Hypertext Preprocessor als wichtigen Tip zu einzelnen Befehlen.

Gruß Rolf