4.4.1 Oggetti SequenceMatcher

La classe SequenceMatcher ha questo costruttore:

class SequenceMatcher( [isjunk[, a[, b]]])
L'argomento facoltativo isjunk deve essere None (il valore predefinito) o una funzione a singolo argomento, che accetti per argomento un elemento della sequenza, e restituisca vero se e solo se l'elemento è ``spazzatura'' e dovrebbe essere ignorato. Passare None per b è equivalente a passare lambda x: 0; vale a dire, nessun elemento viene ignorato. Per esempio, passate:

lambda x: x in " \t"

se state confrontando delle righe come sequenze di caratteri, e non volete che si sincronizzino sugli spazi bianchi o sui caratteri di tabulazione.

Gli argomenti facoltativi a e b sono sequenze da confrontare; il valore predefinito di entrambe è la stringa vuota. Gli elementi di entrambe le sequenze devono essere chiavi valide di una tabella di hash.

Gli oggetti SequenceMatcher hanno i sequenti metodi:

set_seqs( a, b)
Imposta le due sequenze che dovranno essere confrontate.

SequenceMatcher computa e memorizza informazioni dettagliate sulla seconda sequenza, così se volete confrontare una sequenza rispetto a molte sequenze, utilizzate set_seq2() per impostare la sequenza usata più di frequente una volta sola e chiamate set_seq1() ripetutamente, una per ognuna delle altre sequenze.

set_seq1( a)
Imposta la prima sequenze che deve essere confrontata. La seconda sequenza che dovrà essere confrontata non viene cambiata.

set_seq2( b)
Imposta la seconda sequenza che deve essere confrontata. La prima sequenza che dovrà essere confrontata non viene cambiata.

find_longest_match( alo, ahi, blo, bhi)
Trova il più lungo blocco corrispondente in a[alo:ahi] e b[blo:bhi].

Se isjunk viene omesso o è None, get_longest_match() restituisce (i, j, k) così che a[i:i+k] è uguale a b[j:j+k], dove alo <= i <= i+k <= ahi e blo <= j <= j+k <= bhi. Per tutti i (i', j', k') che rispettano queste condizioni, anche le condizioni aggiuntive k >= k', i <= i', e se i == i', j <= j' vengono soddisfatte. In altre parole, di tutti i blocchi massimali di corrispondenza, restituisce quello che inizia per primo in a, e di tutti i blocchi massimali di corrispondenza che iniziano per primi in a, restituisce quello che inizia per primo in b.

>>> s = SequenceMatcher(None, " abcd", "abcd abcd")
>>> s.find_longest_match(0, 5, 0, 9)
(0, 4, 5)

Se isjunk viene fornito, prima viene determinato il più lungo blocco di corrispondenza come indicato sopra, ma con con la restrizione aggiuntiva che nessun elemento spazzatura appaia nel blocco. Quindi il blocco viene esteso il più possibile facendo corrispondere (solo) elementi spazzatura da entrambi i lati. Perciò il blocco risultante non fa mai corrispondere sulla spazzatura ad eccezione di quando spazzatura identica si trova adiacente ad una corrispondenza interessante.

Ecco lo stesso esempio di prima, ma considerando gli spazi bianchi come spazzatura. Questo previene che ' abcd' corrisponda direttamente a ' abcd' alla fine della seconda sequenza. Invece solo 'abcd' può corrispondere e corrisponde l''abcd' più a sinistra nella seconda sequenza:

>>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")
>>> s.find_longest_match(0, 5, 0, 9)
(1, 0, 4)

Se nessun blocco corrisponde, questo restituisce (alo, blo, 0).

get_matching_blocks( )
Restituisce una lista di triple che descrive la sequenza corrispondente. Ogni tripla è nella forma (i, j, n) e significa che a[i:i+n] == b[j:j+n]. Le triple sono funzioni crescenti monotone in i and j.

L'ultima tripla è fittizia e ha il valore (len(a), len(b), 0). È l'unica tripla con n == 0.

>>> s = SequenceMatcher(None, "abxcd", "abcd")
>>> s.get_matching_blocks()
[(0, 0, 2), (3, 2, 2), (5, 4, 0)]

get_opcodes( )
Restituisce una lista di tuple da 5 elementi che descrivono come trasformare a in b. Ogni tupla è nella forma (tag, i1, i2, j1, j2). La prima tupla ha i1 == j1 == 0 e le rimanenti tuple hanno i1 uguale a i2 della tupla precedente e, inoltre, i1 uguale al precedente i2.

I valori tag sono stringhe, con i sequenti significati:

Valore  Significato 
'replace' a[i1:i2] dovrebbe venire sostituito da b[j1:j2].
'delete' a[i1:i2] dovrebbe venire cancellato. Notate che j1 == j2 in questo caso.
'insert' b[j1:j2] dovrebbe venire inserito in a[i1:i1]. Notate che i1 == i2 in questo caso.
'equal' a[i1:i2] == b[j1:j2] (le sotto sequenze sono uguali).

Per esempio:

>>> a = "qabxcd"
>>> b = "abycdf"
>>> s = SequenceMatcher(None, a, b)
>>> for tag, i1, i2, j1, j2 in s.get_opcodes():
...    print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %
...           (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))
 delete a[0:1] (q) b[0:0] ()
  equal a[1:3] (ab) b[0:2] (ab)
replace a[3:4] (x) b[2:3] (y)
  equal a[4:6] (cd) b[3:5] (cd)
 insert a[6:6] () b[5:6] (f)

get_grouped_opcodes( [n])
Restituisce un generatore di gruppi con fino a n righe di contesto.

Partendo con il gruppo restituito da get_opcodes(), questo metodo lo divide in più piccoli gruppi di cambiamenti ed elimina gli intervalli coinvolti, che non hanno cambiamenti.

I gruppi vengono restituiti nello stesso formato di get_opcodes(). Nuovo nella versione 2.3.

ratio( )
Restituisce una misura della similarità delle sequenze, come un numero in virgola mobile nell'intervallo [0,1].

Dove T è il numero totale di elementi in entrambe le sequenze e M il numero delle corrispondenze, questo è 2.0*M / T. Notate che questo è 1.0 se le sequenze sono identiche, e 0.0 se non hanno niente in comune.

Questo è costoso in termini computazionali se get_matching_blocks() o get_opcodes() non sono ancora stati chiamati, nel quale caso potreste voler provare prima quick_ratio() o real_quick_ratio(), per definire un limite superiore.

quick_ratio( )
Restituisce un limite superiore di ratio() in modo relativamente rapido.

Questo non viene definito in altro modo che come un limite superiore su ratio(), ma è più rapido da calcolare.

real_quick_ratio( )
Restituisce un limite superiore di ratio() molto velocemente.

Questo non viene definito in altro modo che come un limite superiore su ratio(), ma è più rapido da calcolare sia di ratio() che di quick_ratio().

I tre metodi che restituiscono il rapporto di corrispondenza rispetto al totale dei caratteri, possono dare risultati differenti dovuti ai diversi livelli di approssimazione, anche se quick_ratio() e real_quick_ratio() sono sempre almeno grandi quanto ratio().

>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75
>>> s.quick_ratio()
0.75
>>> s.real_quick_ratio()
1.0

Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.