#1 2. Februar 2011 String zerlegen in 2 Teile (wie anstellen)?? Hallo zusammmen, ich habe ein kleines Problem. Ich habe mit einer SQL-Abfrage und einem Array einen Namen bzw. mehrere Namen (in einer While Schleife -> Array) ausgelesen und möchte diese nun ausgeben. Soweit alles kein Problem. Doch nun habe ich festgestellt, dass die Namen in der Datenbank im falschen Format stehen. In der Datenbank steht: Mustermann, Max Ich brauche aber: Max Mustermann Meine Frage nun: Kann ich diese Zeichenkette in 2 Teile aufspalten [highlight]$vorname[/highlight] und [highlight]$nachname[/highlight] mit vor dem Komma und Name nach dem Komma? Dann könnte ich sie ja wieder in der anderen Reihenfolge zusammenstückeln... Wie kann man das machen? Gibt es da eine Funktion (die z.Bsp. bis zum Komma sucht und trennt)? Danke. Gruß joker.org + Multi-Zitat Zitieren
#2 2. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? PHP: explode - Manual da powernator mir per pn noch eine andere möglichkeit mit einem regulären ausdruck geschrieben hat, fasse ich das ganze hier nochmal mit einem benchmark zussammen. möglichkeit 1: via explode() möglichkeit 2: via explode() und implode() möglichkeit 3: via substr() und strpos() möglichkeit 4: via preg_replace() PHP: <? php set_time_limit ( 0 ); print 'explode: ' . bench ( 'bench1' ) . '<br />' ;print 'implode/explode: ' . bench ( 'bench2' ) . '<br />' ;print 'substr/strpos: ' . bench ( 'bench3' ) . '<br />' ;print 'preg_replace: ' . bench ( 'bench4' ); function bench ( $fn ) { $time = microtime ( true ); $fn (); return microtime ( true ) - $time ;} // -------------------- function bench1 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) { list ( $nachname , $vorname ) = explode ( ', ' , $name ); $res = " $vorname $nachname " ; }} // -------------------- function bench2 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = implode ( ' ' , array_reverse ( explode ( ',' , $name )));} // -------------------- function bench3 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( $name , ( $p = strpos ( $name , ', ' )) + 2 ) . ' ' . substr ( $name , 0 , $p );} // -------------------- function bench4 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = preg_replace ( '/^([^,]+),\s*(.+)$/' , '$2 $1' , $name );} ergebnis: Code: explode: 0.14805889129639 implode/explode: 0.22759985923767 substr/strpos: 0.14574003219604 preg_replace: 0.22067499160767 mein system: windows 7 x64 @ 4x3,2 ghz @ php5.3.5 + Multi-Zitat Zitieren
#3 3. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? Oder sscanf + Multi-Zitat Zitieren
#4 3. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? Ich denke mal das explode eine Gute Lösung ist, bei Murdoc gleich auf mit "substr/strpos" und bei mir klar in Führung (Auch beim 30. mal) Windows XP | 2x3,1666 Ghz | 4GB Ram Code: explode: 0.128863096237 implode/explode: 0.188436031342 substr/strpos: 0.146018028259 preg_replace: 0.157214164734 + Multi-Zitat Zitieren
#5 3. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? Als Denkanstoss gebe ich noch die Möglichkeit die Datenbank neu zu strukturieren. Lass nur einmal den explode durchlaufen und trenne die namen spalte in vorname, nachname (in MYSQL). Das macht bestimmt nen besseren Benchmark + Multi-Zitat Zitieren
#6 3. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? so, mehr möglichkeiten hab ich nicht gefunden dieses probem zu lösen: PHP: <? php header ( 'Content-Type: text/plain; Charset=UTF-8' ); set_time_limit ( 0 ); ob_implicit_flush ( true ); $count = 10 ; $bench = array ( 'explode' => array(), 'explode/implode' => array(), 'substr/strpos' => array(), 'preg_replace' => array(), 'sscanf' => array(), 'strrchr/strstr' => array(), 'strtok' => array()); print "starte $count durchläufe, bitte warten ...\n" ; for ( $i = 0 ; $i < $count ; ++ $i ) { $bench [ 'explode' ][] = bench ( 'bench1' ); $bench [ 'explode/implode' ][] = bench ( 'bench2' ); $bench [ 'substr/strpos' ][] = bench ( 'bench3' ); $bench [ 'preg_replace' ][] = bench ( 'bench4' ); $bench [ 'sscanf' ][] = bench ( 'bench5' ); $bench [ 'strrchr/strstr' ][] = bench ( 'bench6' ); $bench [ 'strtok' ][] = bench ( 'bench7' ); print '-' ;} $result = array ( '__sort__' => array()); foreach ( $bench as $key => $val ) { $best = 10000000 ; $worst = 0 ; $average = 0 ; foreach ( $val as $time ) { if ( $time > $worst ) $worst = $time ; if ( $time < $best ) $best = $time ; $average += $time ; } $average /= $count ; $result [ $key ] = array ( $best , $worst , $average ); $result [ '__sort__' ][ $key ] = $best ;} unset ( $bench ); asort ( $result [ '__sort__' ], SORT_NUMERIC ); foreach ( $result [ '__sort__' ] as $func => $_ ) { list ( $best , $worst , $average ) = $result [ $func ]; printf ( "\n%-'.15s...: %01.5f (%01.5f) ~ %01.5f" , $func , $best , $worst , $average );} print "\n\nlegende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt]" ; function bench ( $fn ) { $time = microtime ( true ); $fn (); return microtime ( true ) - $time ;} // -------------------- function bench1 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) { list ( $nachname , $vorname ) = explode ( ', ' , $name ); $res = " $vorname $nachname " ; }} // -------------------- function bench2 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = implode ( ' ' , array_reverse ( explode ( ',' , $name )));} // -------------------- function bench3 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( $name , ( $p = strpos ( $name , ', ' )) + 2 ) . ' ' . substr ( $name , 0 , $p );} // -------------------- function bench4 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = preg_replace ( '/^([^,]+),\s*(.+)$/' , '$2 $1' , $name );} // --------------------- function bench5 () { $name = "Musermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { list ( $nachname , $vorname ) = sscanf ( $name , '%s %s' ); $res = substr ( " $vorname $nachname " , 0 , - 1 ); }} // --------------------- function bench6 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( strrchr ( $name , ',' ), 1 ) . ' ' . strstr ( $name , ',' , true );} // --------------------- function bench7 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { $nachname = strtok ( $name , ',' ); $vorname = trim ( strtok ( ',' )); $res = " $vorname $nachname " ; }} ergebnis: Code: starte 10 durchläufe, bitte warten ... ---------- explode...........: 0.11890 (0.14951) ~ 0.12602 substr/strpos.....: 0.14413 (0.17344) ~ 0.15731 strtok............: 0.14672 (0.17042) ~ 0.15170 strrchr/strstr....: 0.14930 (0.18042) ~ 0.15830 sscanf............: 0.19324 (0.22948) ~ 0.20459 explode/implode...: 0.21962 (0.25185) ~ 0.23445 preg_replace......: 0.23101 (0.26505) ~ 0.24578 legende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt] windows 7 x64 2x2,4 ghz @ php5.3.1 + Multi-Zitat Zitieren
#7 5. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? Beim sscanf-bench wird in deinem Beispiel aber auch list und substr mitgezählt. Wenn man die erweiterten C-Pattern benutzt (die leider in der PHP Dokumentation fehlen), dann sollte sscanf am schnellsten sein. PHP: sscanf ( 'Mustermann, Max' , '%[^,], %s' , $nachname , $vorname ); + Multi-Zitat Zitieren
#8 5. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? nope, explode liegt trotzdem vorn. Code: starte 10 durchläufe, bitte warten ... ---------- explode...........: 0.11789 (0.15321) ~ 0.12446 sscanf............: 0.12863 (0.15465) ~ 0.14161 strtok............: 0.14667 (0.16866) ~ 0.15247 substr/strpos.....: 0.14713 (0.16407) ~ 0.15656 strrchr/strstr....: 0.15027 (0.17660) ~ 0.15777 explode/implode...: 0.21152 (0.23752) ~ 0.22633 preg_replace......: 0.22432 (0.25520) ~ 0.23764 legende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt] Spoiler PHP: <? php header ( 'Content-Type: text/plain; Charset=UTF-8' ); set_time_limit ( 0 ); ob_implicit_flush ( true ); $count = 10 ; $bench = array ( 'explode' => array(), 'explode/implode' => array(), 'substr/strpos' => array(), 'preg_replace' => array(), 'sscanf' => array(), 'strrchr/strstr' => array(), 'strtok' => array()); print "starte $count durchläufe, bitte warten ...\n" ; for ( $i = 0 ; $i < $count ; ++ $i ) { $bench [ 'explode' ][] = bench ( 'bench1' ); $bench [ 'explode/implode' ][] = bench ( 'bench2' ); $bench [ 'substr/strpos' ][] = bench ( 'bench3' ); $bench [ 'preg_replace' ][] = bench ( 'bench4' ); $bench [ 'sscanf' ][] = bench ( 'bench5' ); $bench [ 'strrchr/strstr' ][] = bench ( 'bench6' ); $bench [ 'strtok' ][] = bench ( 'bench7' ); print '-' ;} $result = array ( '__sort__' => array()); foreach ( $bench as $key => $val ) { $best = 10000000 ; $worst = 0 ; $average = 0 ; foreach ( $val as $time ) { if ( $time > $worst ) $worst = $time ; if ( $time < $best ) $best = $time ; $average += $time ; } $average /= $count ; $result [ $key ] = array ( $best , $worst , $average ); $result [ '__sort__' ][ $key ] = $best ;} unset ( $bench ); asort ( $result [ '__sort__' ], SORT_NUMERIC ); foreach ( $result [ '__sort__' ] as $func => $_ ) { list ( $best , $worst , $average ) = $result [ $func ]; printf ( "\n%-'.15s...: %01.5f (%01.5f) ~ %01.5f" , $func , $best , $worst , $average );} print "\n\nlegende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt]" ; function bench ( $fn ) { $time = microtime ( true ); $fn (); return microtime ( true ) - $time ;} // -------------------- function bench1 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) { list ( $nachname , $vorname ) = explode ( ', ' , $name ); $res = " $vorname $nachname " ; }} // -------------------- function bench2 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = implode ( ' ' , array_reverse ( explode ( ',' , $name )));} // -------------------- function bench3 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( $name , ( $p = strpos ( $name , ', ' )) + 2 ) . ' ' . substr ( $name , 0 , $p );} // -------------------- function bench4 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = preg_replace ( '/^([^,]+),\s*(.+)$/' , '$2 $1' , $name );} // --------------------- function bench5 () { $name = "Musermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { $vorname = $nachname = '' ; sscanf ( $name , '%[^,], %s' , $nachname , $vorname ); $res = " $vorname $nachname " ; }} // --------------------- function bench6 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( strrchr ( $name , ',' ), 1 ) . ' ' . strstr ( $name , ',' , true );} // --------------------- function bench7 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { $nachname = strtok ( $name , ',' ); $vorname = trim ( strtok ( ',' )); $res = " $vorname $nachname " ; }} ich denke mal, dass die funktion "explode" ganz einfach öfter verwendet (bzw. bekannter ist) und daher von php-entwicklern auf geschwindigkeit optimiert wurde, wohingegen sscanf vermutlich nur in einem wrapper aufgerufen wird. zum vergleichen: Code: starte 10 durchläufe, bitte warten ... ---------- [B]einfache zuweisung...: 0.03555 (0.05501) ~ 0.03792[/B] explode..............: 0.11826 (0.12469) ~ 0.11961 sscanf...............: 0.12795 (0.14718) ~ 0.13774 substr/strpos........: 0.14424 (0.16430) ~ 0.15379 strtok...............: 0.14657 (0.14949) ~ 0.14773 strrchr/strstr.......: 0.15086 (0.15757) ~ 0.15364 explode/implode......: 0.21000 (0.23815) ~ 0.22529 preg_replace.........: 0.21973 (0.23356) ~ 0.22632 legende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt] PHP: // einfache zuweisung function bench0 () { for ( $i = 0 ; $i < 100000 ; ++ $i ) { $vorname = 'Max' ; $nachname = 'Mustermann' ; $res = " $vorname $nachname " ; } } und falls es jemanden interessiert, sscanf in c: 10 x 10.000 wiederholungen (selber benchmark wie in php) Code: 0.01500 (0.01600) ~ 0.01560 sogut wie nicht messbar. 10 x 100.000 wiederholungen Code: 0.03100 (0.04700) ~ 0.04060 immer noch schneller als die einfache zuweisung in php Spoiler Code: #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <string.h> void bench(int, int); void bench1(double *, int); void bench1_fn(int); int main() { bench(10, 10000); bench(10, 100000); /* bench(10, 1000000); */ return 0; } void bench(int count, int times) { int i; double best = 100000, worst = 0, average = 0; for (i = 0; i < count; ++i) { double timer; bench1(&timer, times); /* nicht messbar */ if(timer == 0) { --i; continue; } if (timer < best) best = timer; if (timer > worst) worst = timer; average += timer; } average /= count; printf("sscanf (%d x %d): %01.5f (%01.5f) ~ %01.5f\n", count, times, best, worst, average); fflush(stdout); } void bench1(double *t, int times) { DWORD start = GetTickCount(); bench1_fn(times); *t = (double) (GetTickCount() - start) / 1000.0; } void bench1_fn(int times) { int i; for (i = 0; i < times; ++i) { char name[] = "Mustermann, Max", nachname[11] = { '\0' }, vorname[4] = { '\0' }, result[15] = { '\0' }; sscanf(name, "%[^,], %s", nachname, vorname); strcat(result, vorname); strcat(result, " "); strcat(result, nachname); } } + Multi-Zitat Zitieren
#9 6. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? $vorname = $nachname = ''; Manipulation!!! Spoiler PHP: <? php header ( 'Content-Type: text/plain; Charset=UTF-8' ); set_time_limit ( 0 ); ob_implicit_flush ( true ); $count = 10 ; $bench = array ( 'ZUWEISUNG' => array(), 'explode' => array(), 'explode/implode' => array(), 'substr/strpos' => array(), 'preg_replace' => array(), 'sscanf' => array(), 'strrchr/strstr' => array(), 'strtok' => array(), 'preg_match' => array()); print "starte $count durchläufe, bitte warten ...\n" ; for ( $i = 0 ; $i < $count ; ++ $i ) { $bench [ 'ZUWEISUNG' ][] = bench ( 'bench0' ); $bench [ 'explode' ][] = bench ( 'bench1' ); $bench [ 'explode/implode' ][] = bench ( 'bench2' ); $bench [ 'substr/strpos' ][] = bench ( 'bench3' ); $bench [ 'preg_replace' ][] = bench ( 'bench4' ); $bench [ 'sscanf' ][] = bench ( 'bench5' ); $bench [ 'strrchr/strstr' ][] = bench ( 'bench6' ); $bench [ 'strtok' ][] = bench ( 'bench7' ); $bench [ 'preg_match' ][] = bench ( 'bench8' ); print '-' ; } $result = array ( '__sort__' => array()); foreach ( $bench as $key => $val ) { $best = 10000000 ; $worst = 0 ; $average = 0 ; foreach ( $val as $time ) { if ( $time > $worst ) $worst = $time ; if ( $time < $best ) $best = $time ; $average += $time ; } $average /= $count ; $result [ $key ] = array ( $best , $worst , $average ); $result [ '__sort__' ][ $key ] = $best ; } unset ( $bench ); asort ( $result [ '__sort__' ], SORT_NUMERIC ); foreach ( $result [ '__sort__' ] as $func => $_ ) { list ( $best , $worst , $average ) = $result [ $func ]; printf ( "\n%-'.15s...: %01.5f (%01.5f) ~ %01.5f" , $func , $best , $worst , $average ); } print "\n\nlegende: [beste zeit] ([schlechteste zeit]) ~ [durchschnitt]" ; function bench ( $fn ) { $time = microtime ( true ); $fn (); return microtime ( true ) - $time ; } // -------------------- function bench0 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { $vorname = 'Max' ; $nachname = 'Mustermann' ; $res = $vorname . ' ' . $nachname ; } } // -------------------- function bench1 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) { $array = explode ( ', ' , $name ); $res = $array [ 1 ] . ' ' . $array [ 0 ]; } } // -------------------- function bench2 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = implode ( ' ' , array_reverse ( explode ( ',' , $name ))); } // -------------------- function bench3 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( $name , ( $p = strpos ( $name , ', ' )) + 2 ) . ' ' . substr ( $name , 0 , $p ); } // -------------------- function bench4 () { $name = "Mustermann, Max" ; for ( $i = 0 ; $i < 100000 ; ++ $i ) $res = preg_replace ( '/^([^,]+),\s*(.+)$/' , '$2 $1' , $name ); } // --------------------- function bench5 () { $name = "Musermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { sscanf ( $name , '%[^,], %s' , $nachname , $vorname ); $res = $vorname . ' ' . $nachname ; } } // --------------------- function bench6 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) $res = substr ( strrchr ( $name , ',' ), 1 ) . ' ' . strstr ( $name , ',' , true ); } // --------------------- function bench7 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { $nachname = strtok ( $name , ',' ); $vorname = trim ( strtok ( ',' )); $res = $vorname . ' ' . $nachname ; } } // --------------------- function bench8 () { $name = "Mustermann, Max" ; for( $i = 0 ; $i < 100000 ; ++ $i ) { preg_match ( '/^([^,]+),\s*(.+)$/' , $name , $array ); $res = $array [ 2 ] . ' ' . $array [ 1 ]; } } Allgemein sind solche Performanceoptimierungen hauptsächlich spielereien. Wenn man bedenkt wie viel Zeit und Leistung man für die Lesbarkeit des Codes liegen lässt (Konstruktoren, Getter/Setter, Pattern, etc.), dann jucken einen die Sekundenbruchteile auch keinen mehr. Man sollte immer nach der Mitte zwischen Lesbarkeit und Performance suchen, dann passts. + Multi-Zitat Zitieren
#10 6. Februar 2011 AW: String zerlegen in 2 Teile (wie anstellen)?? nunja, das kam unerwartet, da ich irgendwo (ich denk das war ein podcast) mal aufgeschnappt hatte, dass initialisierte variablen (selbst bei pass-by-reference) flotter sein sollen als uninitialisierte (wobei das innerhalb der schleife recht sinnfrei gewesen ist ^^). so kann man sich täuschen. die sache mit "$foo $bar" vs. $foo . ' ' . $bar ist gewohnheitssache ^^ + Multi-Zitat Zitieren