2014-06-12 8 views
13

Non sono stato in grado di trovare una risposta autorevole a questo, anche se sono sicuro al 99,9% che sia vero. Cose come la answer accettata per fare affidamento sul fatto che sia vera, come mi aspetto un sacco di altro codice. Ma qualcuno che sappia veramente qualcosa su preg_match_all (non per osservazione ma per requisito specificato o algoritmo specificato) conferma che questo è un comportamento garantito? Non riesco a spigolarlo dalla documentazione.L'ordine di un sub-array preg_offset_capture * guaranteed * sta aumentando l'offset?

mio caso d'uso è molto semplice:

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

E so che $regexp non contiene alcun sotto-modelli, in modo la documentazione mi dice che $matches[0] sarà un array di array 2-elemento, dove ciascun sotto-array ha elementi con la chiave numerica 0 contenente una stringa che corrisponde al modello e il tasto numerico 1 contenente l'offset in $content in cui si è verificata la corrispondenza. E mentre sembra ragionevole che gli elementi dell'array vengano ordinati aumentando l'offset, non vedo dove sia richiesto, in modo tale che sarebbe un bug se non fosse il caso. Anche se non riesco a immaginare come si possa ottenere un effetto utile, forse potrebbe esserci un modo per implementare preg_match_all con più thread che aggiungono i loro risultati parziali senza fondersi in un ordine completamente ordinato.

Nel mio caso particolare, mi interessano solo gli offset, non le stringhe abbinate, ma è fondamentale che gli offset aumentino. Quindi, con cintura e bretelle mentalità ho codificato:

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

così si può mettere in un altro modo, è la finale sort($offsets) uno spreco garantito di cicli?

E se non mi mette in grave difficoltà per fare una domanda correlata ma potenzialmente separata, se l'ordinamento fosse potenzialmente utile, sarebbe più/meno/stesso efficiente prendere il flag predefinito SORT_REGULAR come mostrato, o per specificare SORT_NUMERIC esplicitamente, dato che gli offset prodotti all'interno di preg_match_all sono necessariamente numerici?

+0

Interessante domanda. (Ha avuto una risposta, ma ha parlato troppo presto - prima di leggere l'intera domanda - _D'oh! _) – ridgerunner

+0

Qualcuno dovrà guardare il [codice sorgente php] (http://php.net/git.php) :) – zx81

+0

Non capisco davvero la domanda. Ogni elemento abbinato è un elemento dell'array che è anche un array di soli 2 elementi, la stringa con corrispondenza [0] e il suo offset [1]. Non penso che gli offset siano ordinati in un singolo array. Sebbene, questo comportamento potrebbe essere modificabile in combinazione con altre bandiere. Ma dal momento che, costruito in sequenza, è difficile immaginare qualsiasi risultato fuori ordine. Lo stack è usato pesantemente nella regex per mantenere il contesto posizionale. – sln

risposta

6

quanto riguarda la tua domanda su stringa ordine offset:

partite complete devono essere sempre nella stringa crescente offset. PHP implementa la corrispondenza globale con un ciclo che imposta start_offset alla fine della corrispondenza completa più recente fino alla fine della stringa dell'oggetto. Cioè, trova la prima corrispondenza, poi la seconda, quindi la terza e così via.

Se vuoi per verificare che non sto terribilmente fraintendendo il codice sorgente (o manca qualcosa di significativo), si può guardare la funzione php_pcre_match_impl in ext/pcre/php_pcre.c. preg_match_all imposta il parametro globale per 1. Quello che mi risparmiandoci in esso era un commento alla fine del ciclo Do While per global: è impostato

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

Se globale, allora il ciclo si ripete con il nuovo offset e pcre_exec è chiamato di nuovo con esso.

quanto riguarda la tua domanda SORT_NUMERIC:

E 'difficile da dire.L'impostazione SORT_NUMERIC consente di eseguire l'ordinamento utilizzando numeric_compare_function per eseguire confronti tra elementi, dove SORT_REGULAR utilizza compare_function.

compare_function fa un controllo di tipo e poi decide che cosa fare per il confronto da lì, mentre numeric_compare_function converte ciecamente sia in double s. Essendo entrambi LONG compare_function li confronta semplicemente senza alcun tipo di conversione. Quindi alla fine dipende da quale è più veloce: convertire ciecamente a raddoppiare o eseguire il controllo di tipo.

+0

La contrassegno come risposta accettata perché spiega completamente da dove provenivano le informazioni. Non risponde alla domanda come ho chiesto, dove volevo sapere se l'ordinamento era * specificato *. Sembra che non lo sia, quindi un ingegnoso implementatore di php * potrebbe * decidere di ottimizzare il codice esistente per il caso speciale di un pattern di stringa semplice all'interno di un soggetto lungo suddividendo il soggetto in segmenti e cercando in parallelo senza ordinare il risultato finale . Ma con l'attuale implementazione e utilizzo sul campo, questo probabilmente non sarebbe accettato. Ottima risposta su SORT_NUMERIC! – sootsnoot

Problemi correlati