array_multisort() - Array sizes are inconsistent
James
- php
0 ChrisB1 Sven Rautenberg0 Der Martin0 dedlfix0 Der Martin0 dedlfix0 Der Martin0 dedlfix
Hallo,
da ich ja Besserung gelobt habe zuerst mal meine Analyse einer in einer While schleife laufenden Array Sortierung:
foreach ($gewicht_preis_array as $key => $row) {
$gewicht[$key] = $row['Gewicht'];
$preis[$key] = $row['Preis'];
}
array_multisort($gewicht, SORT_ASC, $preis, SORT_ASC, $gewicht_preis_array);
erzeugt den Fehler:
PHP Warning: array_multisort() [<a href='function.array-multisort'>function.array-multisort</a>]: Array sizes are inconsistent in ...
Lasse ich es mit print_r anzeigen print_r ( $gewicht_preis_array );
(vor dem Sortieren):
Array
(
[0] => Array
(
[Gewicht] => 5000
[Preis] => 29.00
)
[1] => Array
(
[Gewicht] => 10000
[Preis] => 34.00
)
[2] => Array
(
[Gewicht] => 20000
[Preis] => 44.00
)
[3] => Array
(
[Gewicht] => 31500
[Preis] => 54.00
)
)
Ist hier nichts auffällig. Zudem lösche ich den Inhalt des Arrays zum Ende der While schleife immer mit
$gewicht_preis_array = array();
Somit sind auch keine Altlasten vorhanden?!?
Hi,
array_multisort($gewicht, SORT_ASC, $preis, SORT_ASC, $gewicht_preis_array);
erzeugt den Fehler:
PHP Warning: array_multisort() [<a href='function.array-multisort'>function.array-multisort</a>]: Array sizes are inconsistent in ...
Die Meldung besagt als, dass mehrere Arrays als Parameter übergeben wurden, deren „Größen“ aber nicht übereinstimmen.
Lasse ich es mit print_r anzeigen
print_r ( $gewicht_preis_array );
(vor dem Sortieren)
[...]
Ist hier nichts auffällig.
Du hast also von den zwei Arrays, die du der Funktion übergibst, dir jetzt eins angeschaut.
MfG ChrisB
Die Meldung besagt als, dass mehrere Arrays als Parameter übergeben wurden, deren „Größen“ aber nicht übereinstimmen.
Welche "Größen" sind denn damit gemeint?
Du hast also von den zwei Arrays, die du der Funktion übergibst, dir jetzt eins angeschaut.
Hm, es gibt ja nur ein Array? Denn $gewicht und $preis werden ja erstellt aus dem Array:
foreach ($gewicht_preis_array as $key => $row) {
$gewicht[$key] = $row['Gewicht'];
$preis[$key] = $row['Preis'];
}
Fehlergefunden,
die Array´s gewicht und preis sind zwar leer aber wenn man sie vorher noch einmal anlegt läuft das Script.
Weiß der Teufel warum das so ist.
Danke für eure Hilfe
James
Moin!
da ich ja Besserung gelobt habe zuerst mal meine Analyse einer in einer While schleife laufenden Array Sortierung:
Dein Code ist ein wunderbares Beispiel für die Schädlichkeit der Existenz der Funktion array_multisort() - oder auch ein Beweis für meine häufig getroffene Aussage: "Wenn du glaubst, array_multisort() benutzen zu müssen, machst du etwas falsch."
foreach ($gewicht_preis_array as $key => $row) {
$gewicht[$key] = $row['Gewicht'];
$preis[$key] = $row['Preis'];
}
array_multisort($gewicht, SORT_ASC, $preis, SORT_ASC, $gewicht_preis_array);
Ok, du produzierst mit einer Extra-Schleife aus einem einzelnen Array, in dem alle Werte drinstehen, noch zwei Extra-Arrays, die die Informationen ganz simpel duplizieren.
Am Ende willst du dann dein Originalarray im Prinzip nur nach Gewicht und danach nach Preis aufsteigend sortiert haben.
Nutze usort()!
> ~~~html
Array
> (
> [0] => Array
> (
> [Gewicht] => 5000
> [Preis] => 29.00
> )
>
> [1] => Array
> (
> [Gewicht] => 10000
> [Preis] => 34.00
> )
>
> [2] => Array
> (
> [Gewicht] => 20000
> [Preis] => 44.00
> )
>
> [3] => Array
> (
> [Gewicht] => 31500
> [Preis] => 54.00
> )
>
> )
Dein Array hat pro Eintrag jeweils einen kompletten Datensatz. Mit usort() und einer passenden Vergleichsfunktion ist das ein Einzeiler (plus die Funktion):
Der Code zum Sortieren:
usort($gewicht_preis_array, 'gewicht_preis_compare');
Und zum Vergleichen:
function gewicht_preis_compare($a, $b) {
if ($a['Gewicht'] == $b['Gewicht']) {
if ($a['Preis'] == $b['Preis']) {
return 0;
}
return ($a['Preis'] < $b['Preis']? -1 : 1);
}
return ($a['Gewicht'] < $b['Gewicht']? -1 : 1);
}
Die Vergleichsfunktion prüft, ob das Gewicht gleich ist. Wenn ja, entscheidet der Preis über die Sortierung. Ist auch der Preis gleich, liefert die Sortierfunktion eine 0 zurück als Info, dass beide Werte gleich sind. Ansonsten liefert die Funktion entweder -1 oder 1 zurück, je nachdem ob der Datensatz $a oder $b kleiner ist gemäß der Sortieranforderung.
- Sven Rautenberg
Hallo,
Nutze usort()!
Und zum Vergleichen:
function gewicht_preis_compare($a, $b) {
if ($a['Gewicht'] == $b['Gewicht']) {
if ($a['Preis'] == $b['Preis']) {
return 0;
}
return ($a['Preis'] < $b['Preis']? -1 : 1);
}
return ($a['Gewicht'] < $b['Gewicht']? -1 : 1);
}
Und das kann man bei gleicher Funktionalität noch etwas kürzer und übersichtlicher schreiben:
~~~php
function gewicht_preis_compare($a, $b)
{ return ($a['Gewicht']==$b['Gewicht'] ? $b['Preis']-$a['Preis'] : $b['Gewicht']-$a['Gewicht']);
}
Wenn das Gewicht gleich ist, gib die Preisdifferenz als Kriterium zurück; andernfalls die Gewichtsdifferenz.
Die Vergleichsfunktion für usort() muss nur 0 für Gleichheit, ansonsten einen Wert <0 bzw. >0 liefern. Der Betrag ist egal. Deshalb ist ein expliziter Vergleich mit nachfolgender Entscheidung für +1 oder -1 nicht nötig, man kann direkt die Differenz zurückgeben und ausnutzen, dass ein Vergleich arithmetisch gesehen nichts anderes als eine Differenzbetrachtung ist.
Ciao,
Martin
Hi!
Und das kann man bei gleicher Funktionalität noch etwas kürzer und übersichtlicher schreiben:
function gewicht_preis_compare($a, $b)
{ return ($a['Gewicht']==$b['Gewicht'] ? $b['Preis']-$a['Preis'] : $b['Gewicht']-$a['Gewicht']);
}
Mit PHP 5.3 ist der [Trinitätsoperator](http://de.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary) erweitert worden, so dass man sogar noch kürzer formulieren kann:
return $b['Gewicht'] - $a['Gewicht'] ?: $b['Preis'] - $a['Preis'];
Außerdem sind Klammern um das gesamte Gebilde überflüssig.
Lo!
Hallo,
function gewicht_preis_compare($a, $b)
{ return ($a['Gewicht']==$b['Gewicht'] ? $b['Preis']-$a['Preis'] : $b['Gewicht']-$a['Gewicht']);
}
> Mit PHP 5.3 ist der [Trinitätsoperator](http://de.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary) erweitert worden
ich weiß - das kann man aber (noch) nicht voraussetzen, solange man bei einigen Hostern schon froh sein muss, wenn man überhaupt auf Wunsch(!) PHP5 anstatt PHP4 haben kann.
> Außerdem sind Klammern um das gesamte Gebilde überflüssig.
Stimmt. Macht's aber IMHO lesefreundlicher (mein persönlicher Eindruck).
So long,
Martin
--
Der geistige Horizont ist der Abstand zwischen Brett und Hirn.
Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
Hi!
Außerdem sind Klammern um das gesamte Gebilde überflüssig.
Stimmt. Macht's aber IMHO lesefreundlicher (mein persönlicher Eindruck).
Finde ich nicht. Es irritiert mich eher, weil ich zunächst auf die Suche nach einer Prioritätsänderung gehe, die von der (-Klammer eingeleitet wird. Wenn ich die schließende )-Klammer erst am Ende finde, stelle ich frustriert fest, dass wieder drei Sekunden meines Lebens sinnlos vergeudet wurden und doch nur die normale Operatoren-Rangfolge gilt.
Lo!
Hallo,
Außerdem sind Klammern um das gesamte Gebilde überflüssig.
Stimmt. Macht's aber IMHO lesefreundlicher (mein persönlicher Eindruck).
Finde ich nicht. Es irritiert mich eher
für mich ist es deshalb angenehmer, weil ich gewöhnt bin, dass bei Kontrollanweisungen - ähnlich wie bei Funktionen - die Argumente in Klammern stehen. Das ist bei if, while, switch und einigen anderen der Fall, daher mach ich es konsequenterweise beim return auch (wohl wissend, dass es eigentlich nicht notwendig wäre).
Zwar wollte mich schon einmal jemand (warst du das nicht sogar?) darauf hinweisen, dass das einen Unterschied machen kann (Wert eines Ausdrucks vs. Referenz), und das nehme ich als Hinweis zur Kenntnis. Doch in den Sprachen und Projekten, die ich bisher vor mir hatte, ist mir noch kein realer Fall untergekommen, wo das relevant gewesen wäre. Denn wenn ich eine Referenz zurückgeben möchte, dann formuliere ich das auch explizit so, z.B. mit dem &-Operator, und empfehle das der Klarheit wegen auch jedem anderen. Und dann ist die Klammerung beim return wirklich nur noch Zierde. In diesem Fall mag ich diese Zierde. ;-)
Wenn ich die schließende )-Klammer erst am Ende finde, stelle ich frustriert fest, dass wieder drei Sekunden meines Lebens sinnlos vergeudet wurden und doch nur die normale Operatoren-Rangfolge gilt.
<pity mode="ironic">Ooooooh ....</pity>
So long,
Martin
Hi!
für mich ist es deshalb angenehmer, weil ich gewöhnt bin, dass bei Kontrollanweisungen - ähnlich wie bei Funktionen - die Argumente in Klammern stehen. Das ist bei if, while, switch und einigen anderen der Fall, daher mach ich es konsequenterweise beim return auch (wohl wissend, dass es eigentlich nicht notwendig wäre).
Da braucht man es aus syntaktischen Gründen um die Bedingung eindeutig vom Anweisungsblock zu trennen. (Bei Python besipsielsweise muss man sie nicht klammern, da wird aber die Bedingung mit einem : abgeschlossen.) Die Ausdrücke von return, continue, break, goto und require/include werden mit ; abgeschlossen, womit syntaktisch bereits alles klar ist.
Zwar wollte mich schon einmal jemand (warst du das nicht sogar?) darauf hinweisen, dass das einen Unterschied machen kann (Wert eines Ausdrucks vs. Referenz), und das nehme ich als Hinweis zur Kenntnis. Doch in den Sprachen und Projekten, die ich bisher vor mir hatte, ist mir noch kein realer Fall untergekommen, wo das relevant gewesen wäre. Denn wenn ich eine Referenz zurückgeben möchte, dann formuliere ich das auch explizit so, z.B. mit dem &-Operator, und empfehle das der Klarheit wegen auch jedem anderen. Und dann ist die Klammerung beim return wirklich nur noch Zierde. In diesem Fall mag ich diese Zierde. ;-)
Diese Zierde wird aber im Funktionskopf vor den Funktionsnamen geschrieben. Beim return sieht man davon nichts mehr. Da darf man nur
return $variable;
notieren. Mit Klammern gibt es eine Notice-Meldung und keine Referenz.
Lo!