Entwickler-Ecke
Programmiersprachen (Server) - PHP8 und Histogramme oder warum hat man das umgestellt?!?
Narses - So 25.06.23 23:57
Titel: PHP8 und Histogramme oder warum hat man das umgestellt?!?
Moin!
Ich quäle mich grade durch die PHP8-Umstellung eines großen Projektes (von PHP7.4.33). Ich kann nachvollziehen, dass der Hinweis (E_NOTICE) für "undefined array key" auf eine Warnung (E_WARNING) hochgestuft wurde. Ich habe sogar tatsächlich deshalb Fehler im Code gefunden, die dort seit Jahren schlummerten (sie waren nicht wirklich schlimm, sonst wären sie ja schon vorher aufgefallen :zwinker:). Aber, immerhin. :mahn:
Nun gibt es aber Situationen, in denen will mir einfach nicht einleuchten, was daran nun "besser" sein soll. Konkret ärgere ich mich immer wieder bei Histogrammen, also dem Zählen der Häufigkeit unbekannter Werte. Hier ein simples Beispiel:
PHP-Quelltext
1: 2: 3: 4: 5: 6:
| $a = array('Apfel', 'Birne', 'Apfel'); $histo = array(); foreach ($a as $key) $histo[$key]++; var_dump($a); var_dump($histo); |
liefert erwartungsgemäß unter PHP8.x:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| Warning: Undefined array key "Apfel" in php8_count_demo.php on line 7 Warning: Undefined array key "Birne" in php8_count_demo.php on line 7
array(3) { [0]=> string(5) "Apfel" [1]=> string(5) "Birne" [2]=> string(5) "Apfel" } array(2) { ["Apfel"]=> int(2) ["Birne"]=> int(1) } |
Klar, man kann entweder einen Dual-Pass-Ansatz wählen und erst die Werte, dann die Häufigkeit ermitteln. Man kann auch bei jedem Wert schauen ob er schon existiert und dann alternativ den Wert mit 1 initialisieren oder sonst inkrementieren. Ist dann "sauberer" Code, aber weder performant noch besser lesbar. :nut:
Also, Fehler unterdrücken und sich jedesmal unwohl fühlen, weil das ja "unsauber" ist... :suspect: :oops:
PHP-Quelltext
1: 2:
| foreach ($a as $key) @$histo[$key]++; |
Was mache ich falsch, was übersehe ich, ist das wirklich von den PHP-Entwicklern so beabsichtigt? Ich kann das irgendwie nicht glauben... :gruebel:
cu
Narses
jaenicke - Mo 26.06.23 01:50
Was spricht denn für diesen Zweck gegen
array_count_values [
https://www.php.net/manual/en/function.array-count-values.php]?
Für andere Zwecke gibt es nun (seit 7.4) den null coalescing assignment operator ??=, mit dem man einen Arrayeintrag zuweisen und dabei ohne Warnung automatisch erstellen kann. Den gibt es leider nicht für den Inkrement-Operator. So etwas wie ??++ wäre schon sehr hilfreich.
Und ja, das ist so beabsichtigt, denn oft fallen Fehler bei der Initialisierung der Arraywerte nicht auf. Was, wenn du eben nicht 0 brauchtest, wenn der Wert noch nicht existiert? Da du mit dem Quelltext ja sagst, dass du dem Wert etwas zuweisen möchtest, finde ich die Warnung folgerichtig. Aber ja, ich habe es in der Vergangenheit auch schon so verwendet. ;-)
Narses - Mo 26.06.23 02:00
Moin!
Die Funktion kann nur Strings und Ints zählen, das ist dem simplen Beispiel geschuldet. Es geht natürlich nicht immer/nur um Strings oder Ints, also keine allgemeine Lösung. :nixweiss:
jaenicke hat folgendes geschrieben : |
Für andere Zwecke gibt es nun (seit 7.4) den null coalescing assignment operator ??=, mit dem man einen Arrayeintrag zuweisen und dabei ohne Warnung automatisch erstellen kann. Den gibt es leider nicht für den Inkrement-Operator. So etwas wie ??++ wäre schon sehr hilfreich. |
Tja, den Operator ??++ fände ich auch schön. ;)
jaenicke hat folgendes geschrieben : |
Und ja, das ist so beabsichtigt, denn oft fallen Fehler bei der Initialisierung der Arraywerte nicht auf. Was, wenn du eben nicht 0 brauchtest, wenn der Wert noch nicht existiert? Da du mit dem Quelltext ja sagst, dass du dem Wert etwas zuweisen möchtest, finde ich die Warnung folgerichtig, wenn es den noch nicht gibt. |
Srsly? :suspect: Was sollte ich mit ++ wohl wollen, den Zeiger auf das nächste Objekt verschieben? Und ein Wert, der nicht vorhanden ist, als 0 anzunehmen, tun wir ja auch an anderen Stellen, also "realitätsfern" ist was anderes... :roll:
jaenicke hat folgendes geschrieben : |
Aber ja, ich habe es in der Vergangenheit auch schon so verwendet. ;-) |
:zwinker:
cu
Narses
jaenicke - Mo 26.06.23 02:05
Die kürzeste Version ohne Warnung dürfte diese sein:
PHP-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| function inc(&$item) { $item++; } $a = array('Apfel', 'Birne', 'Apfel'); foreach ($a as $key) inc($histo[$key]); var_dump($a); var_dump($histo); |
Das lohnt sich natürlich nur, wenn du es öfter ersetzen möchtest. Ob das für alle Fälle geht, weiß ich nicht.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!