{"id":291,"date":"2010-11-22T10:43:02","date_gmt":"2010-11-22T09:43:02","guid":{"rendered":"https:\/\/d-mueller.de\/blog\/?p=291"},"modified":"2016-01-12T00:05:46","modified_gmt":"2016-01-11T23:05:46","slug":"usort","status":"publish","type":"post","link":"https:\/\/d-mueller.de\/blog\/usort\/","title":{"rendered":"usort"},"content":{"rendered":"<p><a href=\"http:\/\/php.net\/manual\/de\/function.usort.php\">usort<\/a> war mir zwar bisher schon bekannt, wirklich benutzt habe ich es aber nicht &#8211; was ich jetzt r\u00fcckblickend bereue. Kurz gefasst ist usort die Waffe der Wahl, wenn man Arrays sortieren m\u00f6chte die entweder <b>heftig verschachtelt<\/b> sind oder f\u00fcr die es keine <b>trivialen Sortierkriterien<\/b> gibt (wie etwa gr\u00f6\u00dfer \/ kleiner). F\u00fcr beides kommen sp\u00e4ter Beispiele. Bisher kam ich zwar auch ohne usort um die Runden, habe aber ersatzweise dann ziemlich aufw\u00e4ndige Ersatzkonstruktionen bauen m\u00fcssen, f\u00fcr die usort die eindeutig bessere Wahl gewesen w\u00e4re.<\/p>\n<h3>Ein Beispiel<\/h3>\n<p>Man nehme folgendes Array:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$data = array(\r\n&quot;P1915&quot; =&gt; array(&quot;name&quot; =&gt; &quot;Manfred Schmidt&quot;, \r\n\t\t\t\t &quot;work&quot; =&gt; array(&quot;income&quot; =&gt; 61000, \r\n\t\t\t\t &quot;pos&quot; =&gt; &quot;Abteilungsleiter&quot;)),\r\n&quot;P2193&quot; =&gt; array(&quot;name&quot; =&gt; &quot;Wilfried Mueller&quot;, \r\n\t\t\t     &quot;work&quot; =&gt; array(&quot;income&quot; =&gt; 42300, \r\n\t\t\t\t &quot;pos&quot; =&gt; &quot;Entwickler&quot;)),\r\n&quot;P0813&quot; =&gt; array(&quot;name&quot; =&gt; &quot;Herbert Mann&quot;, \r\n\t\t\t     &quot;work&quot; =&gt; array(&quot;income&quot; =&gt; 93500, \r\n\t\t\t\t &quot;pos&quot; =&gt; &quot;Chef&quot;)),\r\n&quot;P3913&quot; =&gt; array(&quot;name&quot; =&gt; &quot;Klaus Kaiser&quot;, \r\n\t\t\t     &quot;work&quot; =&gt; array(&quot;income&quot; =&gt; 42700, \r\n\t\t\t\t &quot;pos&quot; =&gt; &quot;Entwickler&quot;)),\r\n&quot;P2881&quot; =&gt; array(&quot;name&quot; =&gt; &quot;Juergen Koenig&quot;, \r\n\t\t\t     &quot;work&quot; =&gt; array(&quot;income&quot; =&gt; 43300, \r\n\t\t\t\t &quot;pos&quot; =&gt; &quot;Marketing&quot;)));\r\n<\/pre>\n<p>Dabei haben wir eine Zuordnung der Personalnummer zu einem Unterarray, welches den Name beinhaltet und weitere Verzweigung auf ein &#8222;work&#8220;-Unterarray mit Position und Gehalt hat. <b>Aufgabe:<\/b> Das Array soll unter Beibehaltung der Personalnummer (also des Array-Keys) absteigend nach dem Gehalt sortiert werden. Ohne usort w\u00e4re das extrem hakelig und aufw\u00e4ndig.<\/p>\n<h4>Die L\u00f6sung<\/h4>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\nuasort($data,function($a, $b) \r\n{\r\n    \/*echo &quot;Comparing &quot;.print_r($a,true).\r\n\t\t   &quot; to &quot;.print_r($b,true).&quot;&lt;br \/&gt;&quot;;*\/\r\n\t\/\/equal -&gt; return 0\r\n\tif ($a[&quot;work&quot;][&quot;income&quot;] == $b[&quot;work&quot;][&quot;income&quot;]) return 0;\r\n\t\/\/highest income at first\r\n\tif ($a[&quot;work&quot;][&quot;income&quot;] &lt; $b[&quot;work&quot;][&quot;income&quot;]) return 1; \r\n\t\/\/lowest income last\r\n\treturn -1; \r\n});\r\n<\/pre>\n<p>Das Ergebnis:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\nArray\r\n(\r\n    [P0813] =&gt; Array\r\n        (\r\n            [name] =&gt; Herbert Mann\r\n            [work] =&gt; Array\r\n                (\r\n                    [income] =&gt; 93500\r\n                    [position] =&gt; Geschaeftsfuehrer\r\n                )\r\n        )\r\n    [P1915] =&gt; Array\r\n        (\r\n            [name] =&gt; Manfred Schmidt\r\n            [work] =&gt; Array\r\n                (\r\n                    [income] =&gt; 61000\r\n                    [position] =&gt; Abteilungsleiter\r\n                )\r\n        )\r\n    [P2881] =&gt; Array\r\n        (\r\n            [name] =&gt; Juergen Koenig\r\n            [work] =&gt; Array\r\n                (\r\n                    [income] =&gt; 43300\r\n                    [position] =&gt; Marketing\r\n                )\r\n        )\r\n    [P3913] =&gt; Array\r\n        (\r\n            [name] =&gt; Klaus Kaiser\r\n            [work] =&gt; Array\r\n                (\r\n                    [income] =&gt; 42700\r\n                    [position] =&gt; Entwickler\r\n                )\r\n        )\r\n    [P2193] =&gt; Array\r\n        (\r\n            [name] =&gt; Wilfried Mueller\r\n            [work] =&gt; Array\r\n                (\r\n                    [income] =&gt; 42300\r\n                    [position] =&gt; Entwickler\r\n                )\r\n        )\r\n)\r\n<\/pre>\n<p>Hierbei sind folgende Aspekte erw\u00e4hnenswert:<\/p>\n<ul>\n<li>Die beiden Variablen $a und $b in der Callback-Funktion sind beliebige Elemente aus dem Array.<\/li>\n<li>usort ist nicht stabil. Hei\u00dft: Sind 2 Werte gleich, kann man sich nicht darauf verlassen, dass sie ihre Reihenfolge behalten<\/li>\n<li>Die Callback-Funktion muss -1, 0 (Beide Werte gleich) oder 1 zur\u00fcckgeben<\/li>\n<li>Ich verwende eine anonyme Callback-Funktion. Das muss nicht sein (siehe n\u00e4chstes Beispiel). Ist auch erst seit PHP 5.3 m\u00f6glich<\/li>\n<li>Ich verwende <b>uasort<\/b>, um die Beziehung zum Array-Key bestehen zu lassen. usort l\u00f6scht bestehende Keys und nummeriert von 0 an aufsteigend neu.<\/li>\n<li>usort (und nat\u00fcrlich auch uasort) verwenden intern das Quicksort-Verfahren. Wie der Vergleich intern durchgef\u00fchrt wird, l\u00e4sst sich gut betrachten wenn man sich im Callback paar Informationen ausgeben l\u00e4sst.<\/li>\n<\/ul>\n<p>Garnicht so schwer, oder?<\/p>\n<h3>Und noch ein Beispiel<\/h3>\n<p>Wir wollen Instanzen einer Klasse in einem Array sortieren. Und zwar Autos nach ihrer PS-Zahl absteigend. <b>Die Klasse:<\/b><\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\nclass Car\r\n{\r\n\tprotected $_hp;\r\n\tprotected $_name;\r\n\t\r\n\tpublic function getHp()\r\n\t{\r\n\t\treturn $this-&gt;_hp;\r\n\t}\r\n\t\r\n\tpublic function getName()\r\n\t{\r\n\t\treturn $this-&gt;_name;\r\n\t}\r\n\t\r\n\tpublic function __construct($name,$hp)\r\n\t{\r\n\t\t$this-&gt;_hp = $hp;\r\n\t\t$this-&gt;_name = $name;\r\n\t}\r\n}\r\n<\/pre>\n<p>Die Instanzen wandern nun in ein Array.<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$cars = array(new Car(&quot;BMW M5&quot;,517),\r\n\t\t\t  new Car(&quot;Audi S3&quot;,220),\r\n\t\t\t  new Car(&quot;Mercedes S600&quot;,620));\r\n<\/pre>\n<p>&#8230;und werden verglichen:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\t\t\t  \r\nusort($cars,&quot;carcompare&quot;);\r\n\r\nfunction carcompare($a, $b)\r\n{\r\n\tif ($a-&gt;getHp() == $b-&gt;getHp()) return 0;\r\n\tif ($a-&gt;getHp() &lt; $b-&gt;getHp()) return 1;\r\n\treturn -1;\r\n}\r\n<\/pre>\n<p>Der Output ist wie gew\u00fcnscht:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\nforeach ($cars as $c) \r\n\techo &quot;&lt;br \/&gt;&quot;.$c-&gt;getName().&quot;: &quot;.$c-&gt;getHp();\r\n\r\n\/*\r\nMercedes S600: 620\r\nBMW M5: 517\r\nAudi S3: 220\r\n*\/\r\n<\/pre>\n<p>Diesmal wird die altbew\u00e4hrte Callback-Variante ohne anonyme Funktion verwendet.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>usort war mir zwar bisher schon bekannt, wirklich benutzt habe ich es aber nicht &#8211; was ich jetzt r\u00fcckblickend bereue. Kurz gefasst ist usort die Waffe der Wahl, wenn man Arrays sortieren m\u00f6chte die entweder heftig verschachtelt sind oder f\u00fcr &hellip; <a href=\"https:\/\/d-mueller.de\/blog\/usort\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,3],"tags":[],"class_list":["post-291","post","type-post","status-publish","format-standard","hentry","category-php","category-webdev"],"_links":{"self":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/291","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/comments?post=291"}],"version-history":[{"count":0,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/291\/revisions"}],"wp:attachment":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/media?parent=291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/categories?post=291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/tags?post=291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}