Intelligentes substr()

 


loeffler
Veteran

22.12.10
23:59 Uhr
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:

  1. function trunc_str($str, $len, $v=3) {
  2. if ($len == 0 || mb_strlen($str) <= $len)
  3. return $str;
  4. if ($len <= $v)
  5. return trim(mb_substr($str, 0, $len))."...";
  6.  
  7. /* Schneidet den String erstmal bis $len ab.
  8. * Kommt an Stelle $len+1 noch ein Leerzeichen,
  9. * wird der abgeschnittene String so ausgegeben.
  10. */
  11. $tmp_str = mb_substr($str, 0, $len);
  12. if (mb_substr($str, $len, 1) == ' ')
  13. return trim($tmp_str);
  14.  
  15. $tmp_len = mb_strlen($tmp_str);
  16.  
  17. /* Schleife läuft für Leerzeichen, Punkt und Bindestrich durch.
  18. * Ermittelt die Position eines jeden Zeichens.
  19. *
  20. * Liegt die Stelle des Zeichens hinter der gewünschten Länge minus der Variablen
  21. * und ist die Differenz zwischen Länge des Strings und der gefundenen Position kleiner
  22. * als der in $diff gespeicherte Wert, werden die Werte sowohl für $pos als auch $diff gesetzt.
  23. */
  24. $diff = $tmp_len;
  25. $tmp_pos = 0;
  26. foreach (array(' ', '.', '-') as $elem) {
  27. $tmp_pos = mb_strrpos($tmp_str, $elem);
  28. if (($tmp_pos >= $len - $v) && ($tmp_len-$tmp_pos < $diff)) {
  29. $diff = $tmp_len-$tmp_pos;
  30. $pos = $tmp_pos;
  31. }
  32. }
  33. /* Existiert $pos, wird an der entsprechenden Stelle abgeschnitten
  34. * Ansonsten an $len minus der Variablen */
  35. if ($pos > 0)
  36. return trim(mb_substr($str, 0, $pos));
  37.  
  38. return trim(mb_substr($str, 0, $len-$v))."...";
  39. }
Quelltext in Zwischenablage kopieren

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?
Link zu diesem Beitrag in die Zwischenablage kopieren
Mister Ad
Werbung
Schon mal bei Zalando, Amazon oder eBay geguckt? Vielleicht wirst du dort fündig.

 
honsey
Gast

23.12.10
00:47 Uhr
wofür braucht man sowas denn?
Link zu diesem Beitrag in die Zwischenablage kopieren
fabian
Veteran

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
Link zu diesem Beitrag in die Zwischenablage kopieren
loeffler
Veteran

23.12.10
10:31 Uhr
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.
Link zu diesem Beitrag in die Zwischenablage kopieren
atzoo
Dauergast

23.12.10
10:55 Uhr
Ich habe so etwas mal programmiert, finde aber die Funktion nicht wieder und ich komm ums Verrecken nicht drauf wo ich die benutzt habe brain

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.
Link zu diesem Beitrag in die Zwischenablage kopieren
loeffler
Veteran

23.12.10
12:48 Uhr
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. planlos
Link zu diesem Beitrag in die Zwischenablage kopieren
atzoo
Dauergast

23.12.10
14:01 Uhr
Hab ja auch nur gesagt wie ich es gemacht habe - oder machen würde bounce
Link zu diesem Beitrag in die Zwischenablage kopieren
Dlr
Zaungast

31.03.13
12:43 Uhr
  1. function supersubstr($s,$l,$r=3){
  2. return mb_substr($s,0,$l).((($_=mb_split("[\x20\-\.]+",
  3. mb_substr($s,$l,$r),~2))&&mb_strlen($_[0])<$r&&isset($_[1]))?$_[0]:'');}
Quelltext in Zwischenablage kopieren
Link zu diesem Beitrag in die Zwischenablage kopieren
Jonis
Veteran

31.03.13
12:57 Uhr
Irrelevanter Beitrag (anzeigen):

Link zu diesem Beitrag in die Zwischenablage kopieren
 
#