[PHP/MySQL] Nur erste 50 Wörter auslesen

bisselbock

Fußballtrainer
ID: 40415
L
4 Mai 2006
90
5
Hallo zusammen,

ich möchte im Sinne einer Newsvorschau nur die ersten 50 Wörter einer News aus der Datenbank auslesen. Sodass man dann auf "mehr" klicken kann und die ganze News angezeigt wird. Geht ja prinzipiell einfach mit substr(), allerdings basiert das ja auf Zeichen. Ich könnte genauso gut sagen: Gib mir nur die ersten 200 Zeichen. Hätte ich auch kein Problem mit, nur möchte ich verhindern, dass ein Wort mittendrin abgeschnitten wird. Versteht ihr?!

Nach meinem Verständnis müssen ich einen Bereich definieren, indem er abschneiden soll und in diesem Bereich nach einem Leerzeichen suchen, oder?
Wie machen ich das? Hat da jemand einen eleganten Vorschlag?
 
Zuletzt bearbeitet:
Dann nimmst die ersten 200 zeichen und suchst das letzte Leerzeichen mit strrpos ab dem dann bis zum Ende alles gelöscht wird.

so in etwa:

$string = substr($string, 0, 200);
$pos= strrpos($string, " ");
$string = substr($string, 0, $pos);
 
Zuletzt bearbeitet:
Und wenn man nur 50 Wörter haben will einfach den Text an " " aufsplitten mittels explode() und per Schleife die ersten 50 Array Elemente auslesen und zu einem neuen String zusammen schreiben ;)

So in der Art:

PHP:
$array = explode(" ", $text, 50);
$ntext = NULL;
for($a = 0; $a < 50; $a++)
  $ntext .= $array[ $a ]." ";
 
Zuletzt bearbeitet:
Falls noch jemand so wie ich bei sowas auf die einzeiligen Varianten steht:
PHP:
$shortened_text = implode(' ', array_slice(explode(' ', $text), 0, 50));
 
hmmm mal ganz umständlich auch noch:

PHP:
$array=explode (" ", $deintext, "50");

$count=0;
while($count<50) {
$text=$text." ".$array[$count];
$count++; }

ja ich weis es geht auch viel einfacher aber diese idee wollt ich auch mal bringen

mfg
 
PHP:
$array=explode (" ", $deintext, "50");

$count=0;
while($count<50) {
$text=$text." ".$array[$count];
$count++; }

Kritik an deiner Lösung.
"50" ist eigentlich kein integer.
Für deinen count gibt's in PHP extra eine for-Schleife (vgl. chrissel).

Die beste Lösung ist imo von tleilax. Übersichtlich, leicht verständlich, kompakt! ;)
 
Besten Dank! Wie sieht das ganze mit der Performance auf? Gibt es da große Unterschiede zwischen den Varianten?
 
Besten Dank! Wie sieht das ganze mit der Performance auf? Gibt es da große Unterschiede zwischen den Varianten?
Die Array-Varianten sind auf jeden Fall langsamer, aber wie groß der Unterschied ist weiss ich nicht. Müsste man mal austesten.

EDIT: hab ich mal gemacht: Die Array-Varianten dauern 10 bis 100 mal länger, je nach Text.
 
Zuletzt bearbeitet:
EDIT: hab ich mal gemacht: Die Array-Varianten dauern 10 bis 100 mal länger, je nach Text.

Wie haste das denn getestet? In einer Schleife? Wie groß? Wie lange war der String? Hast du dann microtime verwendet? Alles nur Fragen rein interessehalber soll keine Kritik sein. Wäre nett, wenn du den Fetzen mal posten könntest.

Hab' die Idee eben dann doch noch - wohl aus nächtlicher Langeweile (oder wegen nicht-schlafen-könnens) doch mal in reguläre Ausdrücke umgesetzt.


Entweder so:
preg_match_all('~([^ ]+ )~s', $str, $t);
print_r(implode('', array_slice($t[0], 0, 50)));


Oder so:
preg_match_all('~((?:[^ ]+ ){0,50})~s', $str, $t);
print_r($t[0][0]);


Keine Ahnung wie schnell (oder eher langsam) die beiden sind, aber funktionieren tun die auch. Beim Testen ist mir allerdings was aufgefallen.. kann's sein, dass es da zu Ungereimtheiten mit dem Zeichensatz kommt?
 
Hatte auch mal in einem anderen Forum gefragt und da war die erste vorgeschlagene Lösung auch ein Regex. Da gab es aber keine Probleme mit dem Zeichensatz... 8O
 
So.. hab grad selber noch eine Funktion geschriebe. Von der Funktionalität her einwandfrei.. ich hab dabei übrigens erst realisiert, dass 50 Wörter wohl nur 49 Leerzeichen dazwischen heißt. Aber sogar das klappte auf Anhieb:

PHP:
function chop_off($str, $limit=50) {
  $length = strlen($str);
  while(true) {
    $substr_count = substr_count($str, ' ', 0, $length);
    if($substr_count > $limit) {
      $length *= .5;
    }
    elseif($substr_count < $limit && $length < strlen($str)) {
      $length *= 1.5;
    }
    elseif($substr_count == $limit) {
      return substr($str, 0, strrpos(substr($str, 0, $length), ' '));
    }
  }
}

echo chop_off($str);

Völlig frei von Arrays. Würde mich interessieren ob das nun schneller ist.
Mir war irgendwie langweilig und ich hatte diese Idee noch im Kopf.. jetzt sollte ich vielleicht endlich besser lernen gehen. :-?
 
PHP:
$off=0;
$off2=0;
for($i=0;$i<50;$i++)
if($off2 = strpos ( $string , " ", $off )) 
$off=$off2; 
elseif(!$off)
$off=strlen($string);
else 
break;
$string = substr($string, 0, $off);
Das wäre auch noch eine Variante, ist aber langsamer als meine andere, wenn es denn wirklich 50 Wörter sein müssen.
 
Zuletzt bearbeitet:
Hier halte ich mich gerade dran auf:
PHP:
preg_match("/^(\w+(?:\W+\w+){1,49})\b/", $row['text'], $text);

Klappt eigentlich wie blöd, allerdings nicht zwingend, wenn es weniger als 50 Wörter sind und ein Punkt (oder anderes Satzzeichen) am Ende steht. Woran liegt es? Ich kann den Regex leider nicht lesen. Ist mir wirklich ein bisschen zu kompliziert.
 
Bevor Ihr Euch noch länger an Unwichtigkeiten aufhaltet, hab ich mal 'n Benchmark gemacht:
Benchmark bei 100.000 Durchläufen
tleilax: 3.9761030674s
chrissel: 5.20983195305s
happymaster_1: 16.4586951733s
happymaster_2: 6.94948601723s
happymaster_3: ungültig, Funktion buggt
DocTrax: 7.48628687859s
bisselbock: 10.1068429947s
Dabei ist nur die Laufzeit geprüft worden, nicht die richtige Funktionsweise.

Man kann sich manchmal schon auf die verfügbaren Funktionen berufen und dabei gute Ergebnisse erzielen... ;)
 
Ah danke.. erneut die Frage, wie du die Performance untersucht hast.. Schleife mit wie vielen Durchläufen? Dann die Zeit angeschaut? Textlänge?

Also bei mir hat die Funktion funktioniert.. wo buggt die? :(
Wobei ich die strpos-Lösung auch noch im Kopf hatte.. die gefällt mir auch gut. Zu dieser konkreten Umsetzung konnt ich aber nicht denken - so weit.

Edit: Überrascht hat mich aber durchaus, dass deine tolle Lösung auch wirklich die schnellste ist! :)
 
Durchläufe stehen da ja - 100.000 pro Funktion und dabei die Laufzeiten addiert. Textlänge habe ich innerhalb dieser Durchläufe nicht variiert, ich denke aber nicht, dass es da grossartige Unterschiede geben würde.

Bei Deiner Funktion gab's den Fehler, dass die in einer Endlosschleife mit der Fehlermeldung, dass der Offset beim substr_count() grösser als die Stringlänge wäre.