La classe SequenceMatcher ha questo costruttore:
[isjunk[, a[, b]]]) |
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:
a, b) |
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.
a) |
b) |
alo, ahi, blo, bhi) |
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)
.
) |
(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)]
) |
(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)
[n]) |
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.
) |
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.
) |
Questo non viene definito in altro modo che come un limite superiore su ratio(), ma è più rapido da calcolare.
) |
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().
>>> 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.