mmofacts.com

Sortierung von Mehrdimensionalen Arrays nach einem der Werte

gepostet vor 17 Jahre, 3 Monate von DrakeL
Hi,
da ich bei php.net nicht direkt was gefunden habe, wollte ich nachfragen, ob jemand von euch eine PHP Funktion (oder eine eigene Funktion) besitzt, die das lösen könnte?
Problem ist: ich hab ein mehrdimensionales Array in der Form in etwa:
 "udo", "punkte" => 500), array("name" => "berndt", "punkte" => 600) ); ?>

Jetzt bräuchte ich eine Funktion, die ein solches Array auf-/absteigend nach dem Namen oder nach den Punkten sortiert (bzw. nach jeder beliebigen "Spalte").
in etwa in der Form:

Als 3. Parameter dann in irgendeiner Form (Konstante oder String) ob auf- oder absteigend sortiert werden soll.
Wüsstet Ihr hier eine elegante Möglichkeit?
gepostet vor 17 Jahre, 3 Monate von Blabbo
ich hab die function zwar nie wirklich verstanden, aber sie funktioniert

function sort_2d_array(&$array, $sort, $d = 1) {
usort ($array, create_function(
'$a,$b',
'return ($a["'.$sort.'"] > $b["'.$sort.'"] ? 1 : -1)* '.$d.';'));
}
$d beschreibt, ob auf- oder absteigend sortiert weden soll
gepostet vor 17 Jahre, 3 Monate von DrakeL
Was verstehst daran nicht? Das heißt du setzt Funktionen ein, die du selbst nicht verstehst? (Ist doch eigentlich der Wartungskiller Nummer 1, wenn da mal nen Bug drin hast *g*)
Typisches Beispiel für "das ist so einfach, da wär ich nie drauf gekommen" ^^.
Mit "usort" definierst deine eigene Sortierfunktion. Die schaut aber nicht, ob der übergebene Wert der einzelnen Indizes größer/kleiner sind. Sondern geht noch eine Stufe tiefer rein und schaut bei dem übergebenen Indize nach.
Danke für die Funktion
. Nun muss ich Sie mir nur noch sauber in OOP umformen (create_function gefällt mir nicht so sehr) mit Fehlerüberprüfung. Nicht dass da einer ein eindimensionales Array reinhaut ^^. Kann ich hier dann posten, wenn ich das hab.
Hast du schon Erfahrungen was die Laufzeit angeht? Auch wenn es für mich irrelevant ist, da es nie mehr als 50 Datensätze sein können, aber doch interessant wie schnell das sortieren mit eigenen Funktionen gemacht wird
gepostet vor 17 Jahre, 3 Monate von Blabbo
Original von DrakeL
Das heißt du setzt Funktionen ein, die du selbst nicht verstehst?

Ja
Ich verstehe ja auch nicht, wie PHP intern arbeitet und setze es ein.
Solche kleinen tool-funktionen muss ich nicht verstehen.
Die Zeit, mich damit zu beschäftigen verbringe ich lieber in Foren,
um anderen Leuten zu helfen
Original von DrakeL

Hast du schon Erfahrungen was die Laufzeit angeht? Auch wenn es für mich irrelevant ist, da es nie mehr als 50 Datensätze sein können, aber doch interessant wie schnell das sortieren mit eigenen Funktionen gemacht wird
Ne, hab da keinerlei tests gemacht.
Bisher wars immer schnell genug, hab aber auch keine großen arrays damit sortiert
gepostet vor 17 Jahre, 3 Monate von DrakeL
Also ich will alles verstehen was ich einsetze (deswegen nutze ich auch nur in Notfällen Bibliotheken wie z.B. Blowfish wo ich mal gebraucht hab, da war es mir ausnahmsweise auch egal, wie es funktioniert ). Allein schon weil ich Sie "sicher" machen will und bei falschen Parametern auch Exceptions werfe oder die Funktionen leicht verändere für meine Bedürfnisse und immer dokumentiere (naja, manchmal vielleicht zuviel ^^).
Mmh, wenn mir jetzt noch jemand sagt, wie ich mehrzeiligen PHP Code posten kann (?) würde ich mein angepasstes Ergebnis posten ^^. Hab aber nur hinzugefügt dass ich es direkt in der Klasse mit Membervariable benutze, beide Elemente überprüft werden, ob es auch Arrays sind und alles bissle dokumentiert, wie es bei mir Standard ist.
gepostet vor 17 Jahre, 3 Monate von planetenkiller
Mmh, wenn mir jetzt noch jemand sagt, wie ich mehrzeiligen PHP Code posten kann (?)

Mache einfach Zeilenumbrüche:

echo "Hallo World!";
?>


echo "Hallo World!";
?>
gepostet vor 17 Jahre, 3 Monate von DrakeL
Dass es geht wusst ich, nur wenn man auf das Dollarzeichen geht, bekommt man nur ein einzeiliges Eingabefeld, aber hab gerade gesehen, ich kanns nach dem Bestätigen des Dialoges in den Tag direkt kopieren *die einfachsten Dinge sind doch die letzten die einem einfallen...* ^^
Falls jemand braucht mit Fehlerüberprüfung (noch ungetestet):

/**
* Sortiert die Tabelle nach der uebergebenen Spalte
*
* Die Funktion definiert eine eigene Sortierfunktion um die Spalten
* innerhalb der Tabellen beliebig sortieren zu koennen
*
* @param string $column Die Spalte, nach der sortiert werden soll
* @param bool $desc "true", fuer eine absteigende Sortierung
*/
public function setSort($column, $desc = false)
{
/*
* Bei jedem Datensatz ueberpruefen, ob beide Elemente ebenfalls
* Arrays sind, bevor auf die Indizes zum Sortieren zugegriffen wird
*/
$sortfunction = 'if(gettype($value) != \'array\' or gettype($compare) != \'array\') { throw new SystemcoreException(); }';

/*
* Unterscheidung, ob ab- oder aufsteigend sortiert werden muss. Dies
* wird hier schon abgegriffen, da es in der Funktion fuer jedes
* Element unterschieden werden muesste und sicher die
* Sortierreihenfolge nicht zwischen zwei Elementen aendern kann
*/
if($desc)
{
$sortfunction .= ' if($value[\'' . $column . '\'] > $compare[\'' . $column . '\'] ) { return 1; } else { return -1; }';
} else
{
$sortfunction .= ' if($value[\'' . $column . '\'] < $compare[\'' . $column . '\'] ) { return 1; } else { return -1; }';
}

/*
* Die Datensaetze der Tabelle mit Hilfe der oben definierten Funktion
* sortieren, um auch jede beliebige Spalte sortierbar zu machen
*/
usort(&$this->rows, create_function('$value, $compare', $sortfunction));
}
gepostet vor 17 Jahre, 3 Monate von planetenkiller
Dass es geht wusst ich, nur wenn man auf das Dollarzeichen geht, bekommt man nur ein einzeiliges Eingabefeld

Das liegt daran, das du im einfachen Modus arbeitest. Man kann über dem Textfeld auf den erweiterten Modus umschalten. Da musst du die Tags aber selber schliessen, bzw. mit den Buttons mit den x darauf.
Wow, du dokumentierst deine Funktionen aber gut. Bei mir ist vielleicht 40% Dokumentiert.
gepostet vor 17 Jahre, 3 Monate von DrakeL
Bei mir sind alle Funktionen bzw. Klassen und Methoden, da ich komplett OOP arbeite (nur 1 Skript, Rest sind Klassen), auf diese Weise dokumentiert.
Klasse und Methode mit PHPDoc Kommentare, damit ich mir später ne API daraus erstellen lassen kann und in der Methode bei jedem Arbeitsschritt eine Kommentierung was hier warum gemacht wird (-> um vielleicht ne Optimierung zu finden, wenn ich nochmal drüber nachdenke warum ich es so mache und auch nach Wochen/Monaten noch weiß was ich mir dabei gedacht hab).
Ich denke, dass sich das später lohnt, wenn ich Bugs suchen muss . Vor allem kann ich auf diese Art meine Gedanken am besten sortieren und es ist oft so, dass ich erst komplett die Kommentierung schreib und dann mit PHP Code auffülle.
Der Code ist dann dann zwar etwas aufgebläht, aber da meine Klassen alle in eigene Dateien sind ist trotzdem (bis auf eine Ausnahme bisher) keine größer als 200 Zeilen.
gepostet vor 17 Jahre, 3 Monate von DrakeL
wenn du mir sagst wie ich damit mein Array vom Eröffnungspost nach Name oder Punkte sortieren kann benutz ich die Funktion gerne
gepostet vor 17 Jahre, 3 Monate von planetenkiller
Das geht aber nur, nachdem er das Array speziell umgekrempelt hat, und und dann neues und altes array und wie sortieren übergeben hat.
Man siehe die Kommentare auf der PHP Seite an.
gepostet vor 17 Jahre, 3 Monate von DrakeL
Hab es mit der eigenen Funktion nun gemacht, funktioniert ohne Probleme, auch mit numerischen Strings .
Jetzt hab ich wenigstens meine Klasse fertig für Datentabellen mit Spaltenformatierung und Sortierung ^^.
Thx für die Hilfestellung
gepostet vor 17 Jahre, 3 Monate von Nightflyer
Aus php.net:
 
function array_alternate_multisort()
{
$arguments = func_get_args();
$arrays = $arguments[0];
for ($c = (count($arguments)-1); $c > 0; $c--)
{
if (in_array($arguments[$c], array(SORT_ASC , SORT_DESC)))
{
continue;
}
$compare = create_function('$a,$b','return strcasecmp($a["'.$arguments[$c].'"], $b["'.$arguments[$c].'"]);');
usort($arrays, $compare);
if ($arguments[$c+1] == SORT_DESC)
{
$arrays = array_reverse($arrays);
}
}
return $arrays ;
}
?>
To demonstrate:
$dir_contents[] = array("is_dir" => 0, "name" => "b.jpg");
$dir_contents[] = array("is_dir" => 1, "name" => "e");
$dir_contents[] = array("is_dir" => 1, "name" => "a");
$dir_contents[] = array("is_dir" => 0, "name" => "d.png");
$dir_contents[] = array("is_dir" => 0, "name" => "c.png");
$dir_sorted = array_alternate_multisort($dir_contents, "is_dir", SORT_DESC, "name", SORT_ASC);
print_r($dir_sorted);
?>
Produces the output:
Array
(
[0] => Array
(
[is_dir] => 1
[name] => a
)
[1] => Array
(
[is_dir] => 1
[name] => e
)
[2] => Array
(
[is_dir] => 0
[name] => b.jpg
)
[3] => Array
(
[is_dir] => 0
[name] => c.png
)
[4] => Array
(
[is_dir] => 0
[name] => d.png
)
)
gepostet vor 17 Jahre, 3 Monate von DrakeL
Mmh, die Methode ist gleich der von oben, nur dass Sie mehrere Spalten erlaubt nach denen sortiert wird, oder sehe ich das falsch?
Sehr gut wenn man es braucht, nur mit schon wieder zu komplex, da ich so etwas nie brauchen werde
PS: ich brauch dies bei Tabellen, sodass man auf jede Überschrift der Tabelle klicken kann und die Tabelle dann nach dieser sortiert wird. Man kann ja schlecht zwei Überschriften anklicken ^^.
gepostet vor 17 Jahre, 3 Monate von Blabbo
sowas macht man doch am besten gleich mit sql, oder?!
gepostet vor 17 Jahre, 3 Monate von DrakeL
Nicht wenn die Tabellenklasse allgemein gehalten ist und man Daten per PHP als einzelne Zeilen hinzufügen kann. Egal woher diese kommen.
Klar, bei Daten aus der Datenbank werde ich das so machen, dafür wird die Klasse nochmal vererbt (denk ich mal, dass es so dann am geschicktesten ist) und die Sortiermethode überschrieben, dass Sie nen Order By in das Statement reinsetzt, das übergeben wird.
Soll ja später keine feste Spalte sein, nach der sortiert wird, sondern die, wo man drauf klickt.
gepostet vor 17 Jahre, 3 Monate von Klaus
Original von Blabbo
sowas macht man doch am besten gleich mit sql, oder?!

SQL wäre auch 10x schneller.
Die Performance bei PHP-Arrays ist allgemein sehr schlecht. Das ist nun mal der Preis typenfreier assoziativer mehrdimensionaler Arrays.

Auf diese Diskussion antworten