Du bist nicht angemeldet (anmelden)
Seite 1
Intelligentes substr()
Editiert: 23.12.10, 00:05 Uhr
Hallo zusammen,ich bin derzeit auf der Suche nach einer Möglichkeit, einen String halbwegs „intelligent“ zu trennen. Was genau ich mir darunter vorstelle: Man gibt eine maximale Länge des Strings an, aber anstatt an der Stelle direkt den String abzuschneiden, soll erstmal überprüft werden, ob ein Trennzeichen (in meinem Falle Leerzeichen, Punkt und Bindestrich) sich in der „Nähe“ befindet. Wenn das der Fall ist, wird an dem entsprechendem Zeichen getrennt, ist das Zeichen allerdings zu weit weg, wird der String ganz normal getrennt.
Per Google hab ich nichts brauchbares gefunden, weshalb ich mir folgende Funktion gebasltet habe (das „sich in der Nähe befinden“ wird durch den Paramter $v ausgedrückt). Ich hoffe, es ist halbwegs verständlich:
function trunc_str($str, $len, $v=3) {if ($len == 0 || mb_strlen($str) <= $len)return $str;if ($len <= $v)return trim(mb_substr($str, 0, $len))."...";/* Schneidet den String erstmal bis $len ab.* Kommt an Stelle $len+1 noch ein Leerzeichen,* wird der abgeschnittene String so ausgegeben.*/$tmp_str = mb_substr($str, 0, $len);if (mb_substr($str, $len, 1) == ' ')return trim($tmp_str);$tmp_len = mb_strlen($tmp_str);/* Schleife läuft für Leerzeichen, Punkt und Bindestrich durch.* Ermittelt die Position eines jeden Zeichens.** Liegt die Stelle des Zeichens hinter der gewünschten Länge minus der Variablen* und ist die Differenz zwischen Länge des Strings und der gefundenen Position kleiner* als der in $diff gespeicherte Wert, werden die Werte sowohl für $pos als auch $diff gesetzt.*/$diff = $tmp_len;$tmp_pos = 0;foreach (array(' ', '.', '-') as $elem) {$tmp_pos = mb_strrpos($tmp_str, $elem);if (($tmp_pos >= $len - $v) && ($tmp_len-$tmp_pos < $diff)) {$diff = $tmp_len-$tmp_pos;$pos = $tmp_pos;}}/* Existiert $pos, wird an der entsprechenden Stelle abgeschnitten* Ansonsten an $len minus der Variablen */if ($pos > 0)return trim(mb_substr($str, 0, $pos));return trim(mb_substr($str, 0, $len-$v))."...";}
Soweit, so gut - es ist leider immer noch nicht ganz perfekt. Ich hab allerdings auch das Gefühl, dass ich die Sache etwas zu umständlich angehe und das es möglicherweise eine wesentlich einfachere Lösung gibt.
Irgendwelche Tipps, Hinweise, vorgefertigte Funktionen oder sonst was?
ließe sich sicherlich mit RegEx deutlich vereinfachen... aber'n beispiel kann ich dir auf die schnelle auch nicht geben
honsey schrieb am 23.12.10, 00:47 Uhr:
wofür braucht man sowas denn?
Mh, ich finds einfach unschön, wenn ein String an einer unpassenden Stelle abgeschnitten wird, obwohl zwei Zeichen vorher eine viel bessere Möglichkeit wäre.
Im konkreten Fall geht es um ein Wordpress Widget, dass Lied-Titel in der Sidebar anzeigt. Da gibt es zum einen Titel, die relativ viele Leerzeichen enthalten, wo es also Sinn machen würde, da zu trennen. Andere enthalten wiederum gar keine, also muss man trotzdem wieder ganz normal trennen.
fabian schrieb am 23.12.10, 01:54 Uhr:
ließe sich sicherlich mit RegEx deutlich vereinfachen... aber'n beispiel kann ich dir auf die schnelle auch nicht geben
An RegEx hab ich auch schon gedacht, ich hab aber absolut keinen Ansatz gefunden. Zumal ich mich auch jedes mal wieder neu einarbeiten muss, wenn ich was mit RegEx mache.
Ich habe so etwas mal programmiert, finde aber die Funktion nicht wieder und ich komm ums Verrecken nicht drauf wo ich die benutzt habe 
Habe aber auch nur auf Leerzeichen geprüft - nicht wie du auch auf Bindestriche, Punkt, etc und (Kurzform) habs einfach über ein explode() bei den Leerzeichen gemacht und dann wieder zusammengesetzt bis maxlength überschritten und die letzte Stelle des Leerzeichens überprüft ob erneut geschnitten werden muss/kann.
Du könntest natürlich auch nur die Range (max Länge +/- Zeichen die noch zusätzlich erlaubt sind) auf die Sonderzeichen überprüfen die du zulassen willst und dann schneiden. Also prüfen ob in den Stellen 15 - 25 die erlaubten Trennzeichen sind und dann an der gewünschten Position schneiden.
Habe aber auch nur auf Leerzeichen geprüft - nicht wie du auch auf Bindestriche, Punkt, etc und (Kurzform) habs einfach über ein explode() bei den Leerzeichen gemacht und dann wieder zusammengesetzt bis maxlength überschritten und die letzte Stelle des Leerzeichens überprüft ob erneut geschnitten werden muss/kann.
Du könntest natürlich auch nur die Range (max Länge +/- Zeichen die noch zusätzlich erlaubt sind) auf die Sonderzeichen überprüfen die du zulassen willst und dann schneiden. Also prüfen ob in den Stellen 15 - 25 die erlaubten Trennzeichen sind und dann an der gewünschten Position schneiden.
Aber das würd doch ziemlich nah an das kommen, was ich bereits hab - zumindest, wenn du das so meinst, wie ich mir das denke. Ob ich jetzt den kompletten String nehme und alle Positionen bis zu Länge - Zusatz ausschließe, oder den String einfach um Länge - Zusatz kürze. Die Abfrage würd etwas anders aussehen, aber einen direkten Vorteil seh ich da jetzt nicht.
function supersubstr($s,$l,$r=3){return mb_substr($s,0,$l).((($_=mb_split("[\x20\-\.]+",mb_substr($s,$l,$r),~2))&&mb_strlen($_[0])<$r&&isset($_[1]))?$_[0]:'');}
