Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
  Druckansicht

  (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
Autor Nachricht
    BeitragVerfasst: 02.07.2009 23:23 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
Hallo Leute,

ich arbeite derzeit wieder an nem kleinen Script. Meine PHP Kenntnisse sind immernoch äußerst bescheiden, deswegen benutze ich etwas, was ich im Web gefunden habe:

http://board.gulli.com/thread/766131-ph ... weitern/#9

Damit kann ich CSV Dateien sortiert ausgeben. Nun gibt es in meiner CSV Datei eine kleine Besonderheit. Eine meiner Spalten besitzt Inhalt der nicht rein alphabetisch oder nummerisch sortiert werden kann. Folgendermaßen sieht der aus:
Von 9d bis 1d, von 1k bis 30k

wobei 9d > 8d > ... > 1d>1k > ... > 9k > 10k > .... > 30k

Mit der Sortierfunktion im Link funktioniert das (natürlich) überhaupt nicht.

Da ich nun keine Ahnung habe, wie ich an die Sache rangehen kann und da meine Programmierkenntnisse immernoch äußerst bescheiden sind, wollte ich mal nach einem Ansatz fragen, wie ich an so etwas rangehen kann. Hat einer ne Idee?


Nach oben
 Profil  
 

  
    BeitragVerfasst: 03.07.2009 00:46 
Co-Admin
Co-Admin
Benutzeravatar
Offline

Beiträge: 3349
Registriert: 18.12.1999 02:01
Wohnort: From Hell
ähm hä?

Sind das die einzigen Werte in der CSV? Poste doch mal ein, zwei Zeilen...

Was genau willst du denn sortieren? Sind die Werte schon sortiert, oder durcheinander? Willst du eine gelistete Aufführung?:
Code:
9d
8d
7d
...

und

9k
10k
11k
...


Also die ersten Werte $x."d" absteigend und die anderen $y."k" aufsteigend?

Sind es immer die gleichen Werte, besonders meine ich die Buchstaben und ist immer die gleiche Auflistung gewünscht? Dann könnte man, zwar etwas umständlich, if-schleifen einbauen die einen Teil der CSV ASC und den anderen Teil DESC sortieren ... denke ich, sollte machbar sein.

________________________
Bild
Erst nachdem wir alles verloren haben, haben wir die Freiheit, alles zu tun.
Specs: knotenberlin.de/pc.html


Nach oben
 Profil E-Mail senden  
 

  
    BeitragVerfasst: 03.07.2009 02:04 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
Eine normale CSV Datei sieht etwas so aus
Code:
ID;Name;Vorname;Rang;Stadt
1;Wurst;Hans;5d;Wurststadt
2;Hansen;Hänschen;10k;Köln
3;Peterson;Sveni;2d;Jerusalem


Beim Eintragen in der CSV Datei sortiere ich nichts. Ich packe die neuen Einträge immer mit einer neuen ID ans Ende der Datei. Die Id ist einfach ein vorlaufender Zähler.

Die sortierte Ausgabe für die anderen Spalten funktioniert bereits mit dem Script aus dem Gulli Board, für die Ränge (hier Spalte 4) jedoch nicht.

Im Endeffekt ist die Ausgabe eine simple Auflistung aller Einträge in der CSV Datei in der ich zusätzlich jede Spalte aufsteigend und absteigend sortieren kann:
Code:
function ausgabe() {
   GLOBAL $su;

   $datei = fopen("datei.csv","r");   
   
   // Alles einlesen
   while (($data = fgetcsv ($datei, 1000, ";")) !== false ) {
      $csv[] = $data;
   }
   fclose ($datei);
   
   // .. und sortieren
   $sort_column = (isset($_GET['sortcolumn']) ? $_GET['sortcolumn'] : 0);
   $sort_order  = (isset($_GET['sortorder']) ? $_GET['sortorder'] : 'ASC');
   $csv = sortmddata($csv, $sort_column, $sort_order);
   
   //Beginn des Outputs.
   $o = '<!-- Beginn of Anmeldeliste Output -->' . "\n";
   $o .= '<table width="650px" border="1" cellpadding="4" cellspacing="0">'. "\n";      
   $o .= '<tr>'. "\n";
   $o .= '<th><a href="?'.$su.'&sortcolumn=1&amp;sortorder=DESC">runter</a><a href="?'.$su.'&sortcolumn=1&amp;sortorder=ASC">hoch</a>'.$plugin_tx['csv_ausgabe']['ausgabe_name']. '</th>'. "\n";
   $o .= '<th><a href="?'.$su.'&sortcolumn=2&amp;sortorder=DESC">runter</a><a href="?'.$su.'&sortcolumn=2&amp;sortorder=ASC">hoch</a>' .$plugin_tx['csv_ausgabe']['ausgabe_vorname']. '</th>'. "\n";

   //$o .= '<th><a href="?'.$su.'&sortcolumn=3&amp;sortorder=DESC">runter</a><a href="?'.$su.'&sortcolumn=3&amp;sortorder=ASC">hoch</a>' .$plugin_tx['csv_ausgabe']['ausgabe_rang']. '</th>'. "\n";
   $o .= '<th>' .$plugin_tx['csv_ausgabe']['ausgabe_rang']. '</th>'. "\n";
   $o .= '<th>' .$plugin_tx['csv_ausgabe']['ausgabe_stadt']. '</th>'. "\n";
   $o .= '</tr>'. "\n";

   //Ausgabe der CSV
   foreach ($csv as $row) {
      $o .= '<tr>'. "\n";
      $o .= '<td>' .$row[1]. '</td>'. "\n";
      $o .= '<td>' .$row[2]. '</td>'. "\n";
      $o .= '<td>' .$row[3]. '</td>'. "\n";
      $o .= '<td>' .$row[4]. '</td>'. "\n";
      $o .= '</tr>'. "\n";
   }
   $o .= '</table>'. "\n";
   $o .= '<!-- END of Anmeldeliste Output -->' . "\n";

   //Ausgabe weitergeben
   return $o;
}


Nach oben
 Profil  
 

  re: (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
    BeitragVerfasst: 03.07.2009 08:50 
Moderator
Moderator
Benutzeravatar
Offline

Beiträge: 1533
Registriert: 19.04.2002 01:01
Wohnort: Ulm
Ich hab zwar ein-zwei Ideen wie das gehen könnte, aber erstens fehlts mir gerade ein wenig an der Zeit und zweitens komm ich gerade mit den mehrdimensionalen Arrays in PHP nicht wirklich klar :hmpf:

Aber vielleicht helfen ja meine Ansätze:
Entweder du probierst mal usort aus. Damit kann man Arrays anhand einer selbstdefinierten "Vergleichsfunktion" sortieren. Ein eindimensionales Array mit solchen "Rang"-Einträgen lässt sich damit ziemlich einfach sortieren; bei mehrdimensionalen Arrays bin ich gescheitert.

Alternativ könntest du auch dein Array zeilenweise durchgehen und in nem separaten Array indizieren, welche Buchstaben du hast; dazu könntest du z.B. das Schema verwenden, dass alle Einträge mit "*d" ihre ID zugewiesen bekommen, und alle Einträge mit "*k" den Wert "ID+Arraylänge". Mit array_multisort könntest du dann nämlich das Buchstaben-Index-Array sortieren und dabei wird auch parallel dein Daten-Array mitsortiert. Für die Zahlen könntest du das ganze in einem zweiten Schritt wiederholen.
Aber auch hier bin ich an der Mehrdimensionalität gescheitert :(

Ich hoffe, dass meine Ansätze nicht völliger Unsinn sind und dass ich dir ein wenig weiterhelfen konnte ;)

________________________
"Ich habe keinen Stil. Ich bin ich." - Helge Schneider


Nach oben
 Profil  
 

  
    BeitragVerfasst: 03.07.2009 11:23 
Co-Admin
Co-Admin
Benutzeravatar
Offline

Beiträge: 3349
Registriert: 18.12.1999 02:01
Wohnort: From Hell
trotzdem muss man schon wissen, wie genau die Auflistung aussehen soll, bevor man entsprechend Code programmieren kann.

Entweder wird die Auflistung immer 1d,2d,3d....1k,2k,3k,4k (ASC) oder halt umgekehrt 4k,3k,2k,1k....4d,3d,2d,1d (DESC). Dein erster Beitrag las sich allerdings so, als wenn du den einen Teil in ASC und den anderen in DESC brauchen würdest - zeitgleich. Also, wie jetzt?

________________________
Bild
Erst nachdem wir alles verloren haben, haben wir die Freiheit, alles zu tun.
Specs: knotenberlin.de/pc.html


Nach oben
 Profil E-Mail senden  
 

  
    BeitragVerfasst: 03.07.2009 12:36 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
Du hast den ersten Beitrag schon richtig verstanden:
9d > 8d > ... > 1d>1k > ... > 9k > 10k > .... > 30k
Erst absteigend von 9d bis 1d (DESC), dann aufsteigend von 1k bis 30k (ASC)

Ich überleg gerade ob man jedem Wert eine Zahl zuordnet, also:
30k = 10
29k = 20
28k = 30
..... usw.
1k = 300
1d = 310
2d = 320
...
9d = 390

Diesen Wert schreibt man dann in die CSV (allerdings weiß ich grad auch nicht wie man das umsetzen soll). Wenn man die Datei wieder ausgibt wird aus z.B. 120 wieder der 19k. Wahrscheinlich ist das doppelt gemoppelt und sehr umständlich. Auf ne andere Idee komm ich grad nicht. usort() hab ich noch nicht ganz verstanden.

Gruß


Nach oben
 Profil  
 

  re: (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
    BeitragVerfasst: 03.07.2009 13:58 
Moderator
Moderator
Benutzeravatar
Offline

Beiträge: 1533
Registriert: 19.04.2002 01:01
Wohnort: Ulm
Geht's so?

Code:
for($i=1; $i<count($csv); $i++){ // Datei zeilenweise durchlaufen
   if(strcmp(substr($csv[$i][3],-1),"d")==0){ // Fall 1: Rang gleich "d"
      $csv[$i][5] = 1000 - chop($csv[$i][3],"dk");         
   }
   else{ // Fall 2: Rang gleich "k"
      $csv[$i][5] = 1000 + chop($csv[$i][3],"dk");
   }
}

$csv = sortmddata($csv, 5,'ASC');


Ist zwar ziemlich "hässlich" programmiert, aber es dürfte funktionieren - da wird jetzt ein extra Index erstellt, so wie du es angeregt hast.
Habe die "sortmddata" nicht da, daher kann ich es nicht testen...

________________________
"Ich habe keinen Stil. Ich bin ich." - Helge Schneider


Nach oben
 Profil  
 

  Re: re: (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
    BeitragVerfasst: 03.07.2009 14:33 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
Moonwulf hat geschrieben:
Habe die "sortmddata" nicht da, daher kann ich es nicht testen...


Siehe Gulli Link im ersten Beitrag.

Ich werd deine Variante heute Abend mal testen. Vielen Dank schonmal für die Mühe


Nach oben
 Profil  
 

  
    BeitragVerfasst: 03.07.2009 14:44 
Co-Admin
Co-Admin
Benutzeravatar
Offline

Beiträge: 3349
Registriert: 18.12.1999 02:01
Wohnort: From Hell
Das
Code:
if(strcmp(substr($csv[$i][3],-1),"d")==0)
ginge auch so
Code:
if(preg_match("/d/", $csv[$i][3]))


@moonwulf: ist es nicht etwas gewagt extra eine eigene "virtuelle" csv-Spalte zu belegen? Was wenn sich die csv noch erweitert? Dann gibt es an dieser Stelle probleme.

________________________
Bild
Erst nachdem wir alles verloren haben, haben wir die Freiheit, alles zu tun.
Specs: knotenberlin.de/pc.html


Nach oben
 Profil E-Mail senden  
 

  
    BeitragVerfasst: 03.07.2009 16:04 
Co-Admin
Co-Admin
Benutzeravatar
Offline

Beiträge: 3349
Registriert: 18.12.1999 02:01
Wohnort: From Hell
ich hab das gerade mal ausprobiert und festgestellt, dass $i = 0 sein muss, da die CSV, wenn ich das richtig verstanden habe, keinen Kopf (Zeile 0) mit "ID,Name,Vor....usw" hat. Sonst würde das Script so wie es funktioniert, nicht funktionieren. Ich hab mal als Spalte 55 genommen - so geht man evt konflikten besser aus dem weg.

so sollte das klappen:
Code:
   // .. und sortieren
   $sort_column = (isset($_GET['sortcolumn']) ? $_GET['sortcolumn'] : 0);
   $sort_order  = (isset($_GET['sortorder']) ? $_GET['sortorder'] : 'ASC');

// ab hier moonwulfscode //
   if($sort_column=="3") {
   for($i=0; $i<count($csv); $i++) { // Datei zeilenweise durchlaufen
        $sort_column=55;
   if(preg_match("/d/", $csv[$i][3])) { // Fall 1: Rang gleich "d"
      $csv[$i][55] = 1000 - chop($csv[$i][3],"dk");       
      }
   else { // Fall 2: Rang gleich "k"
      $csv[$i][55] = 1000 + chop($csv[$i][3],"dk");
      }
   }
  }
// END moonwulf //

   $csv = sortmddata($csv, $sort_column, $sort_order);


Das Listing ASC sieht dann so aus:
Code:
u    F    1k    Leipzig
t    G    2k    Gießen
s    H    3k    Fenn
x    C    5k    Jerusalem
z    A    9d    Wurststadt
y    B    8d    Köln
w    D    7d    Berlin
v    E    6d    Bonn

DESC so:
Code:
v    E    6d    Bonn
w    D    7d    Berlin
y    B    8d    Köln
z    A    9d    Wurststadt
x    C    5k    Jerusalem
s    H    3k    Fenn
t    G    2k    Gießen
u    F    1k    Leipzig


Wie man sieht, wird *d bei ASC aber erst als Zweites gelistet ... hab jetz adhoc aber keine Lösung.

________________________
Bild
Erst nachdem wir alles verloren haben, haben wir die Freiheit, alles zu tun.
Specs: knotenberlin.de/pc.html


Nach oben
 Profil E-Mail senden  
 

  
    BeitragVerfasst: 03.07.2009 18:10 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
wow das ist schonmal nen großerartiger Entwurf. Der Fehler steckt irgendwo in der Rechnung. Hab mal bisschen rumgespielt

Code:
// ab hier moonwulfscode //
   if($sort_column=="3") {
   for($i=0; $i<count($csv); $i++) { // Datei zeilenweise durchlaufen
        $sort_column=55;
   if(preg_match("/d/", $csv[$i][3])) { // Fall 1: Rang gleich "d"
      $csv[$i][55] = 1000 + chop($csv[$i][3],"dk"); //9d = 1009, 8d=1008, 7d=1007 ... 1d = 1001     
      }
   else { // Fall 2: Rang gleich "k"
      $csv[$i][55] = 100 + chop($csv[$i][3],"dk"); // 1k = 101, 2k = 102...,30k = 130
      }
   }
  }
// END moonwulf //


Ist mein Verständnis bezüglich der Punkte richtig? (Siehe Kommentare)

Bei der Variante oben wird folgendes Ausgegeben

Code:
E    V    1d    Z    A
B    Y    2d    Z    A
F    U    2d    Z    A
G    T    3d    Z    A
C    X    6d    Z    A
H    S    1k    Z    A
A    Z    3k    Z    A
B    Y    29k    Z    A
D    W    29k    Z    A
bzw.
Code:
B    Y    29k    Z    A
D    W    29k    Z    A
A    Z    3k    Z    A
H    S    1k    Z    A
C    X    6d    Z    A
G    T    3d    Z    A
B    Y    2d    Z    A
F    U    2d    Z    A
E    V    1d    Z    A


EDIT achso: das A ist ne 5 Spalte die ich im Orinalscript noch mit drin habe.


Nach oben
 Profil  
 

  
    BeitragVerfasst: 03.07.2009 18:59 
Moderator
Moderator
Benutzeravatar
Offline

Beiträge: 1533
Registriert: 19.04.2002 01:01
Wohnort: Ulm
JMD hat geschrieben:
ist es nicht etwas gewagt extra eine eigene "virtuelle" csv-Spalte zu belegen? Was wenn sich die csv noch erweitert? Dann gibt es an dieser Stelle probleme.

Ja, schon klar. Ist ja auch nur ein schlampiger Entwurf ;-) Das müsste Striker halt anpassen, aber die 55 von dir sind ja auch nicht schlecht :D

JMD hat geschrieben:
ich hab das gerade mal ausprobiert und festgestellt, dass $i = 0 sein muss

Hab gedacht, dass die Dateien einen Header enthalten; so wie Striker weiter oben das Beispiel gemacht hat. Naja egal, ggf. muss das halt bei 0 starten.


@striker: Jetzt bin ich etwas verwirrt. Wenn du das Script so veränderst, dann erhälst du doch folgende Ordnung:

1k, 2k, ... , 30k, 1d, 2d, ..., 9d

Und das wolltest du doch nicht, oder?!? :?

________________________
"Ich habe keinen Stil. Ich bin ich." - Helge Schneider


Nach oben
 Profil  
 

  
    BeitragVerfasst: 03.07.2009 20:53 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
ne, wollte es wie ganz oben. Wollte mit meinem Beispiel nur aufzeigen wo der Fehler ist (sein könnte)

Frage:
Wo wird das k bzw. d wieder an den String geheftet?


Nach oben
 Profil  
 

  re: (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
    BeitragVerfasst: 03.07.2009 22:26 
allgemeingebildete Kreatur
allgemeingebildete Kreatur
Benutzeravatar
Offline

Beiträge: 2235
Registriert: 01.10.2000 01:01
Ok Jungs, ich habs.

Fragt mich nicht wie ich drauf gekommen bin:
Try And Error :)

Code:
// ab hier moonwulfscode //
   if($sort_column=="3") {
   for($i=0; $i<count($csv); $i++) { // Datei zeilenweise durchlaufen
        $sort_column=55;
   if(preg_match("/d/", $csv[$i][3])) { // Fall 1: Rang gleich "d"
   echo $csv[$i][3];
      $csv[$i][55] = (10 - rtrim($csv[$i][3],"dk"))/100;
   echo '='. $csv[$i][55].'<br>'; 
      }
   else { // Fall 2: Rang gleich "k"
      echo $csv[$i][3];
      $csv[$i][55] = (10 + rtrim($csv[$i][3],"dk"))/100;
   echo '='. $csv[$i][55]. '<br>'; 
      }
   }
  }
// END moonwulf //


Die Echos hab ich eingebaut um zu sehen was im Hintergrund passiert:

In der Moonwulf/JMD Variante geben die echos folgendes aus:
3k=13
29k=39
2d=8
6d=4
29k=39
1d=9
2d=8
3d=7
1k=11
10k=20
15k=25
20k=30
30k=40

In meiner /100 Variante folgendes:
3k=0.13
29k=0.39
2d=0.08
6d=0.04
29k=0.39
1d=0.09
2d=0.08
3d=0.07
1k=0.11
10k=0.2
15k=0.25
20k=0.3
30k=0.4

Warum auch immer. PHP kann offensichtlich nicht richtig mit den ganzen Zahlen umgehen. Oder es liegt an der sortmddata(). Glaub ich aber nicht. Jedenfalls werden durch die /100 die Zahlen genau so ausgegeben wie sie ausgegeben werden sollen.

Hat noch jemand Verbesserungsvorschläge?
Ansonsten würde ich das wohl so lassen :)


Nach oben
 Profil  
 

  re: (PHP) Sortierte Ausgabe einer CSV (mit Besonderheit)
    BeitragVerfasst: 07.07.2009 23:13 
Neuankömmling
Benutzeravatar
Offline

Beiträge: 33
Registriert: 18.06.2009 00:06
Huhu, hatte mal probiert, und denke so sollte es gehen, also zumindest sortiert es nach der 3 Spalte, und dort eben nach Striker-Regeln:
(strnatcmp ist da ziemlich nützlich)
Code:
function sort_by_asc($first, $second)
{
    return sort_by_dk($first, $second, 1);
}
function sort_by_dsc($first, $second)
{
    return sort_by_dk($first, $second, -1);
}

function sort_by_dk($first, $second, $dir)
{
    if (substr($first[3], -1) == "d") {
        if (substr($second[3], -1) == "d")
            return strnatcmp($first[3], $second[3]) * $dir;
        else
            return $dir;
    } else {
        if (substr($second[3], -1) == "k")
            return strnatcmp($first[3], $second[3]) * $dir * -1;
        else
            return $dir * -1;
    }
}

usort($csv, "sort_by_dsc"); // z.B. absteigend

Tja, eigentlich finde ich das auch ziemlich selbsterklärend, deswegen,
bis später. :) Achja, $first und $second sind aus der ersten Spalte des mehrdim. Arrays.
preg_* würde ich allgemein vermeiden, zumindest wenn die CPU-Zeit knapp ist.

visitor


Nach oben
 Profil  
 

Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


  Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
RSS-Feed
Impressum und Kontakt
Style created by phpBB3 styles , ziola alveo akuna
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Optimized by SEO phpBB
Deutsche Übersetzung durch phpBB.de