2014-06-12 5 views
13

Ich konnte keine verbindliche Antwort darauf finden, obwohl ich 99,9% sicher bin, dass es wahr ist. Dinge wie die akzeptierten answer auf sich zu verlassen, es ist wahr, wie ich es von vielen anderen Code erwartet. Aber kann jemand, der wirklich etwas über preg_match_all weiß (nicht durch Beobachtung, sondern durch spezifizierte Anforderung oder spezifizierten Algorithmus) bestätigen, dass dies garantiertes Verhalten ist? Ich kann es nicht aus der Dokumentation herauslesen.Ist die Reihenfolge eines preg_offset_capture-Sub-Arrays * garantiert * größer Offset?

Mein Anwendungsfall sehr einfach:

preg_match_all("/$regexp/", $content, $matches, PREG_OFFSET_CAPTURE); 

Und ich weiß, dass $regexp keine Untermuster enthält, so dass die Dokumentation sagt mir, dass $matches[0] wird ein Array von 2-Element-Arrays sein, wobei jedes Unterfeld Elemente mit dem numerischen Schlüssel 0 enthält, der eine Zeichenfolge enthält, die mit dem Muster übereinstimmt, und numerischer Schlüssel 1, der den Versatz in $content enthält, bei dem die Übereinstimmung aufgetreten ist. Und während es nur vernünftig erscheint, dass die Array-Elemente durch zunehmenden Offset geordnet sind, sehe ich nicht, wo das erforderlich ist, so dass es ein Fehler wäre, wenn es nicht der Fall wäre. Obwohl ich mir nicht vorstellen kann, wie man es sinnvoll einsetzen könnte, könnte es vielleicht eine Möglichkeit geben, preg_match_all mit mehreren Threads zu implementieren, die ihre Teilergebnisse anhängen, ohne in eine vollständig sortierte Reihenfolge zu gehen.

In meinem speziellen Fall interessiere ich mich nur für Offsets, nicht für die übereinstimmenden Strings, aber es ist wichtig, dass die Offsets zunehmen. Also mit Riemen und Strapsen Mentalität I codiert:

preg_match_all("/$regexp/", $content, $matches, PREG_OFFSET_CAPTURE); 
$offsets = array(); 
foreach ($matches as $match) { 
    $offsets[] = $match[1]; 
} 
sort($offsets); 

So anders ausgedrückt, ist der letzte sort($offsets) eine garantierte Verschwendung von Zyklen?

Und wenn es mich nicht in tiefe Schwierigkeiten bringt, eine verwandte, aber potentiell getrennte Frage zu stellen, wenn die Sorte potentiell nützlich wäre, wäre es mehr/weniger/gleich effizient, das Standardflag SORT_REGULAR wie gezeigt zu nehmen, oder explizit anzugeben, SORT_NUMERIC, da die innerhalb preg_match_all erzeugten Offsets notwendigerweise numerisch sind?

+0

Interessante Frage. (Hatte eine Antwort, aber sprach zu früh - bevor ich die ganze Frage gelesen habe - _D'oh! _) – ridgerunner

+0

Jemand muss sich den [PHP Quellcode] (http://php.net/git.php) ansehen :) – zx81

+0

Ich verstehe die Frage nicht wirklich. Jedes übereinstimmende Element ist ein Array-Element, das auch ein Array von nur zwei Elementen ist, die übereinstimmende Zeichenfolge [0] und ihr Offset [1]. Ich denke nicht, dass die Offsets in einem einzigen Array angeordnet sind. Obwohl dieses Verhalten möglicherweise in Kombination mit anderen Flags geändert werden kann. Aber da es sequentiell aufgebaut ist, ist es schwer, sich irgendwelche Out-of-Order-Ergebnisse vorzustellen. Der Stapel wird in Regex stark verwendet, um den Positionskontext beizubehalten. – sln

Antwort

6

In Bezug auf Ihre Frage auf String-Offset Reihenfolge:

Voll Matches immer in aufsteigender String-Offset sein sollte. PHP implementiert den globalen Abgleich mit einer Schleife, die den Wert start_offset am Ende der letzten vollständigen Übereinstimmung bis zum Ende der Zeichenfolge festlegt. Das heißt, es findet die erste Übereinstimmung, dann die zweite, dann die dritte, und so weiter.

Wenn Sie möchten, um zu überprüfen, dass ich den Quellcode nicht schrecklich bin Verlesen (oder etwas Wichtiges fehlt), können Sie auf die Funktion aussehen php_pcre_match_impl in ext/pcre/php_pcre.c. preg_match_all den globalen Parameter auf 1 setzt Was mich clued hinein ein Kommentar am Ende des do while-Schleife für global war:

/*Advance to the position right after the last full match*/ 
start_offset = offsets[1]; 

Wenn global gesetzt ist, dann wiederholt sich die Schleife mit dem neuen Offset und pcre_exec wird wieder damit aufgerufen.

In Bezug auf Ihre SORT_NUMERIC Frage:

Es ist schwer zu sagen.Einstellung SORT_NUMERIC macht Sortierung verwenden numeric_compare_function Element Vergleiche zu tun, wobei SORT_REGULARcompare_function verwendet.

compare_function hat eine Typprüfung und entscheidet dann, was von dort für den Vergleich zu tun, während numeric_compare_function nur blind beide wandelt in double s. Mit beiden LONG compare_function vergleicht sie nur ohne irgendeine Art von Konvertierung. Es kommt also letztendlich darauf an, was schneller ist: blind auf Double zu konvertieren, oder die Typprüfung durchzuführen.

+0

Ich markiere dies als die akzeptierte Antwort, weil es vollständig erklärt, woher die Informationen kamen. Es beantwortet die Frage nicht so, wie ich es gefragt habe, wo ich wissen wollte, ob die Bestellung * spezifiziert * wurde. Es scheint, dass dies nicht der Fall ist, also könnte ein schlauer Php-Implementierer * den existierenden Code für den Spezialfall eines einfachen Stringmusters innerhalb eines langen Subjekts optimieren, indem er das Subjekt in Segmente aufteilt und parallel sucht, ohne das Endergebnis zu ordnen . Aber mit der derzeitigen Implementierung und Verwendung in diesem Bereich würde das wahrscheinlich nicht akzeptiert werden. Große Antwort auf SORT_NUMERIC! – sootsnoot

Verwandte Themen