Newsgroup: it.comp.lang.visual-basic
Titolo: [OT Forse] Algoritmo di somiglianza

Ciao a tutti.
Spero che il thread non sia OT, in caso contrario chiedo scusa
anticipatamente.
Ho questo problema (da risolvere in vb).
Mi servirebbe un algoritmo che trovasse la somiglianza di una certa parola
in un database di termini.
Mi spiego meglio
Se voglio inserire in una tabella contenente i nomi di tutti gli editori
italiani il termine:
Mondaori (quindi potenzialmente errato)
e nel db č presente l'editore Mondadori,
vorrei che mi venisse restituito un messaggio che mi avverte del possibile
errore.
(un po come fa google quando si inserisce una parola scorretta; ad esempio
alsoritmo anzichč algoritmo).
Quindi mi devo costruire un algoritmo (il piů efficiente possibile) per fare
questo.
Sono estremamente graditi link a risorse online sul tema.
Grazie a tutti quelli che hanno avuto la pazienza di leggere.
Ciao
Stefano

 in un database di termini.
c'era una soluzione di implementazione abbastanza rapida, che consisteva nel
"delegare" questo controllo al correttore sintattico di word.
Ovviamente ha tutta una serie di controindicazioni, la prima che mi viene in
mente è che word deve essere installato sul pc su cui si fa girare il
programma, inoltre non saprei come definire un "vocabolario" ristretto che
faccia al caso tuo in luogo di quello di default di word, però potrebbe
essere uno spunto.
Salutoni
Sergio

 
E' una idea, non un algoritmo.
Esegui una serie di istruzioni LIKE del tipo:
WHERE campo1 LIKE 'M%'
WHERE campo1 LIKE 'Mo%'
WHERE campo1 LIKE 'Mon%'
...
...
WHERE campo1 LIKE 'Mondao%'
...
e attribuisci una sorta di punteggio al risultato. Poi proponi 
all'utente il valore con il punteggio migliore ...
ciao
	maxx
-- 
NOSPAM: Rimuovere i trattini dallo username!
Cut hyphens from my username!

 Sergio
E' un grosso limite che word debba essere installato sul computer
dell'utente.
Grazie lo stesso.
Stefano

 maxx
Ciao.
Cosě potrebbe funzionare se non sbalgio la prima lettera, altrimenti ...
Oltretutto non č molto performante.
Considera che lo stesso metodo lo dovrei usare su una tabella di Autori
contenente svariate decine di migliaia di record.
Grazie lo stesso.
Stefano


La select non credo sia troppo lenta. Probabilmente il problema sorge 
nel confronto tra i risultati ottenuto dalle diverse query...
Per restringere i risultati e velocizzare puoi pensare di fare un 
controllo supponendo che solo un carattere sia errato:
LIKE '?bcde'
LIKE 'a?cde'
LIKE 'ab?de'
aggiungendo magari anche:
LIKE '?abcde'
LIKE 'abcde?'
in questo modo i risultati restituiti dalle query sono molti meno ...


 in un database di termini.
Esiste la funzione SoundEx() (non implementata in VB) che restituisce una
stringa di 4 caratteri (l'iniziale maiuscola più tre che indicano il peso
calcolato assegnando un punteggio a ogni lettera a seconda dell'importanza
di quella lettera nell'alfabeto).
Parole simili dovrebbero avere iniziale uguale e peso simile.
In Access (SQL) se non sbaglio è implementata.
Altrimenti cerca in google l'algoritmo (lo puoi trovare anche tra i sorgenti
di PHP).
Ciao.


'#### CUT FROM HERE ####
Option Explicit
Private Const SoundexLen = 4
' equivalenze
Private Const strEquivA As String = "ÁÀÂÃÄÅ"
Private Const strEquivE As String = "ÈÉÊË"
Private Const strEquivC As String = "Ç"
Private Const strEquivI As String = "ÌÍÎÏ"
Private Const strEquivN As String = "Ñ"
Private Const strEquivO As String = "ÒÓÔÕÖ"
Private Const strEquivU As String = "ÙÚÛÜ"
Private Const strEquivY As String = "ÝY"
' pesi
Private Const strWeight As String = "AEHIOUYWBPFVCSKGJQXZDTLMNR"
Private Const valWeight As String = "00000000111122222222334556"
Private Function IsBaseAscii(ByVal iAsciiVal As Integer) As Boolean
IsBaseAscii = (iAsciiVal >= 65 And iAsciiVal <= 122)
End Function
Private Function IsExtAscii(ByVal iAsciiVal As Integer) As Boolean
IsExtAscii = (IsBaseAscii(iAsciiVal) Or (iAsciiVal >= 192 And
iAsciiVal <= 221))
End Function
Private Function set_weight(ByVal strAscii As String) As String
Dim pos As Integer
pos = InStr(strWeight, strAscii)
If (pos = 0) Then
set_weight = " "
Else
set_weight = Mid$(valWeight, pos, 1)
End If
End Function
Private Function filtra_Ascii(ByVal charAscii As String) As String
Dim iAscii As Integer
If IsExtAscii(Asc(charAscii)) Then
If InStr(strEquivA, charAscii) <> 0 Then
charAscii = "A"
ElseIf InStr(strEquivE, charAscii) <> 0 Then
charAscii = "E"
ElseIf charAscii = strEquivC Then
charAscii = "C"
ElseIf InStr(strEquivI, charAscii) <> 0 Then
charAscii = "I"
ElseIf charAscii = strEquivN Then
charAscii = "N"
ElseIf InStr(strEquivO, charAscii) <> 0 Then
charAscii = "O"
ElseIf InStr(strEquivU, charAscii) <> 0 Then
charAscii = "U"
ElseIf InStr(strEquivY, charAscii) <> 0 Then
charAscii = "Y"
End If
filtra_Ascii = charAscii
Else
filtra_Ascii = ""
End If
End Function
Public Function soundex(ByVal sWord As String) As String
On Error GoTo error_handler
Dim iLen As Integer
Dim chrTmp As String
Dim sPesi As String
Dim wPesi As String
Dim tmpWeight As String
Dim pos As Integer
Dim i As Integer
iLen = Len(sWord)
' Se la stringa e' vuota, esce.
If (iLen = 0) Then Exit Function
' Converte la stringa in maiuscolo.
sWord = UCase$(sWord)
' Converte lettere accentate nelle equivalenti non accentate.
For i = 1 To iLen
chrTmp = Mid$(sWord, i, 1)
If Not IsBaseAscii(Asc(chrTmp)) Then
Mid$(sWord, i, 1) = filtra_Ascii(chrTmp)
End If
Next
' Scarta punteggiatura e caratteri non appartenenti all'alfabeto.
i = 1
While i <= iLen
If Not IsExtAscii(Asc(Mid$(sWord, i, 1))) Then
sWord = Left$(sWord, i - 1) & Mid$(sWord, i + 1)
iLen = iLen - 1
End If
i = i + 1
Wend
' Attribuzione dei pesi.
sPesi = Space$(iLen)
For i = 1 To iLen
Mid$(sPesi, i, 1) = set_weight(Mid$(sWord, i, 1))
Next
' Se il 2° carattere ha lo stesso peso del 1° carattere elimina il
secondo peso.
If Mid$(sPesi, 2, 1) = Left$(sPesi, 1) Then Mid$(sPesi, 2, 1) = 0
' scarta peso 1a lettera
sPesi = Mid$(sPesi, 2)
iLen = iLen - 1
' Elimina i pesi duplicati o uguali a 0.
i = 1
wPesi = Space$(iLen)
While i <= iLen
tmpWeight = Mid$(sPesi, i, 1)
If Val(tmpWeight) <> 0 And InStr(wPesi, tmpWeight) = 0 Then
Mid$(wPesi, i, 1) = tmpWeight
End If
i = i + 1
Wend
' Elimina blank dalla stringa pesi.
wPesi = Trim$(wPesi)
pos = InStr(wPesi, " ")
Do Until pos = 0
wPesi = Left$(wPesi, pos - 1) & Mid$(wPesi, pos + 1)
pos = InStr(wPesi, " ")
Loop
' inserisce in testa la 1a lettera
sPesi = Left$(sWord, 1) & wPesi
' se il codice e' inferiore alla lunghezza massima, accoda 0;
' se il codice e' superiore alla lunghezza massima, tronca il
codice.
iLen = Len(sPesi)
If (iLen < SoundexLen) Then
sPesi = sPesi & String$(SoundexLen - iLen, "0")
ElseIf (iLen > SoundexLen) Then
sPesi = Left$(sPesi, SoundexLen)
End If
' Restituisce il codice soundex.
soundex = sPesi
Exit Function
error_handler:
Err.Raise Err.Number, "soundex", Err.Description
End Function

 in un database di termini.
Come diceva anche Zanna, l'algoritmo soundex potrebbe fare al caso tuo,
anche se è mirato principalmente sui cognomi inglesi ;-)
Comunque trovi tutta la documentazione qui:
http://www.sitocomune.com/download/sdx_info.zip
<Polemica>
Ti avrei volentieri postato il link alla pagina sito, invece che al file, se
i nostri colleghi del sito comune di Access non avessero implementato questo
script in tutte le loro pagine:
  <SCRIPT LANGUAGE="JavaScript">
    if(self.location==parent.location){
    location.href="../index.html";
</Polemica>
Ciao
*Roby*

     location.href="../index.html";
caspita, roby, già che siamo ot, potresti chiarirmi il significato di questa
parte del messaggio?
Sono mostruosamente curioso... ;-)
Salutoni
Sergio

 
Sei passato dalla polemica ai fatti?
Il sito e' irraggiungibile!! ;-)


 ha scritto

non so se lo chiedi sul serio. comunque direi serva a rispedire
all'index generale se arrivi alla pagina da un'altra provenienza.
sbaglio roby ?

 Sono mostruosamente curioso... ;-)
La tua curiosità è ora  mostruosamente soddisfatta. :-)
Ciao
*Roby*

 non so se lo chiedi sul serio.
Si, davvero, sono mostruosamente ignorante, oltre che mostruosamente
curioso.
Salutoni e ringraziamenti
Sergio

 soluzione del quesito. :-)
ti ringrazio della localizzazione.
devo implementarlo anch'io e mi chiedevo come cercarlo... :)

 Sergio
curioso si', ma il resto non mi sembrava proprio.
ciao

[Roberto Piazzolla] ha scritto:
(snip)
non so se ringraziare per una risposta ot č inutile intasamento di banda....
;-)
Comunque grazie
Salutoni
Sergio

 curioso si', ma il resto non mi sembrava proprio.
spero (per me) che si tratti solo di ignoranza specialistica.
non so dove ho letto che gli altri ci valutano per quello che sappiamo, noi
ci svalitiamo per quello che ignoriamo....
Salutoni
Sergio

 sbaglio roby ?
No, è giusto.
Di solito però ci si preoccupa di queste cose solo per evitare che altri
aprano le tue sottopagine dall'interno di frame del loro sito, fregandoti i
contenuti senza citarti, non certo per tagliare fuori i motori di ricerca.
Invece in questo caso, non solo c'è il problema coi link dei motori, ma
anche la prima possibilità non viene assolutamente contrastata. Se vuoi la
conferma, salva ciò che segue come Html e facci sopra doppio click:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<HTML>
<HEAD>
</HEAD>
<FRAMESET COLS="115,*">
  <FRAME NAME="Left">
  <FRAME NAME="Main" SRC="
http://www.sitocomune.com/general/general059.htm
">
  </FRAMESET>
</FRAMESET>
<NOFRAMES>
</NOFRAMES>
</HTML>
Ciao
*Roby*

 --
Ciao, purtroppo una soluzione del genere è troppo empirica, se le lettere
sbagliate fossero 2 (o più considerando nomi lunghi) sarebbe pressochè
inutile.
Grazie comunque.
Stefano

 contenuti senza citarti, non certo per tagliare fuori i motori di
ricerca.
maro' quante cose non so :)
a me serve solo perche' molte se non tutte le pagine sono impostate
con frame, thumbs ecc. e se uno arriva sul singolo frame si perde
tutto il senso che pensavo nella pagina.
il prossimo sito lo faccio a colpi di .mht da 300k cad, tanto basta
scrivere 'ottimizzato per ie [e banda larga]' :)


Ciao, grazie per l'indicazione inizio a studiarci su.
Stefano

Grazie a tutti per i suggerimenti.
Studierò il materiale segnalato da a.p. e da Roberto Piazzolla.
Un enorme grazie a tutti per la disponibilità dimostrata.
Ciao
Stefano

 in questo modo i risultati restituiti dalle query sono molti meno ...
Fermi ho io la soluzione :
on error goto err:
...
.recordsource=tuaparola
.refresh
...
err:
  msgbox "Impara a scrivere cEcAtO!"
^_^

 tutto il senso che pensavo nella pagina.
Esatto, condivido pienamente , anche io di solito faccio pagine senza
nemmeno un link che vanno in un frame principale , se ci arrivi direttamente
no ci capisci niente del sito , mi siace per le single-page , ma anche io
uso lo stesso metodo !


magari bastasse quello!!!
:o)
ciao
Stefano

 nemmeno un link che vanno in un frame principale ,
A quanto mi dicono quella dei frame è tecnologia superata. Se fai caso tutti
i portali e i siti "seri" non ne usano (se non per aprire altri siti
mantenendo un link all'indietro, come fa ad esempio Google per le
traduzioni).
Ormai tutti usano Asp o Php per generare le pagine complete, potendo in
questo modo facilmente modificare menu e parti fisse del sito senza bisogno
di usare frame per tenere in una pagina unica le parti di interfaccia.
Detto questo, se non si vuole avere un sito con un programma dietro, i frame
diventano una necessità, ma (a mio parere) conviene di più lasciare
all'utente la possibilità di aprire la pagina finale direttamente, e
inserirci di base un link all'home page, che riportarcelo di forza. E'
controproducente, perché se un motore di ricerca mi porta ad una pagina, e
la pagina mi riporta all'home page, stai pur certo che io su quel sito lì
non ci torno più ;-)
Piuttosto è meglio (se proprio si vuole) che ogni pagina richiami la
homepage passandogli il proprio nome,  in modo che l'home-page in fase di
caricamento riapra la pagina stessa. Anche qui serve un programmino lato
server, però.
Vabbè, siamo _veramente_ off-topic ;-)
Ciao
*Roby*

 ha scritto

non piu' che con le interfacce.
e' tecnologia anche l'impostazione che si da', e quanto
violentemente/dolcemente si vuole impostare la relazione con
l'utente/visitatore/cliente.
su questa, come la metti, sono d'accordo. e' infatti il motivo
principale per cui non l'ho ancora implementata.
sul discorso della tecnologia superata, l'avevo sentito dire, e vedo
anch'io che ora molte pagine sono impostate come dici.
pero'
1. sul 'superato' ci sarebbe molto da dire. e' tecnologia superata
anche vb...
2. come dici tu non ho nessunissima voglia di perdere tempo a
imparararmi un altro semi-linguaggio come asp, per sentirmi dire fra
un anno che e' tecnologia superata. a parte il ridicolo di
implementare un db online per una cagnetta e tre poesie in croce, il
poco tempo che ho preferisco passarlo facendo foto e passeggiate. o
usando vb6 per generarmele, le pagine. come alle parole, alle immagini
ci tengo, da circa 35 anni, e vederne l'uso su internet mi da' un
lieve senso di nausea.
3. sulla tecnologia, e l'uso di iconografia e grafica sulla rete,
stenderei un velo pietoso. le pagine msdn, per dirne una, brillano per
sovraccarico di informazioni inutili e scarsa leggibilita'. non e' mai
chiaro se il punto centrale e' all'inizio, al centro o alla fine. sui
portali, sintetizzo: m***a allo stato brado. l'altro giorno cercavo
per un amico come fare una casella gratis virgilio/tin: dopo 10' ho
deciso che o ero del tutto rincoglionito o non e' molto chiaro. il
portale dice che si puo', ma i link evidenti puntano ai servizi a
pagamento. se un po' di programmatori e accatiemmellatori si
imparassero anche qualche concetto di gestalt, magari banalmente
guardando i segnali stradali (quando navigo ho all'incirca gli stessi
margini di percezione che ho quando guido), andrebbe forse un po'
meglio. forse. contro molte stupidita' non c'e' rimedio nozionistico
che tenga. e vorrei anche capire perche' alle 7 del mattino devo
aspettare, in dsl, 60" per avere una pagina di repubblica con 15 foto
del menga. a quell'ora voglio sapere subito i titoli, poi decidere se
approfondirne qualcuno. e per subito intendo un numero di secondi in
cifra singola. ma perche' la capiscano bisognera' aspettare che google
news sia localizzato e spazzi via i quotidiani come l'altro ha gia
fatto coi motori. sono anni che non compro quotidiani, smettero' anche
con quelli in rete. tanto. anche punto informatico rischia brutte
derive, pero' quella cagata che riempiva mezza pagina dinamicamente
(avverbio magico <g>) l'hanno tolta. vuol dire che ragionano. visto
quel popup a pieno schermo sul carlino online ? un amico mi diceva che
fanno bene perche' i banner non vengono piu' percepiti (e' il mio
caso, se sulla pagina c'e' qualcosa che si muove il mio subconoscio
riesce magicamente a escluderlo dalla percezione): fatto sta che ho
personalmente ho abolito il carlino, anche se per il locale ci
capitavo. i popup posso accettarli su astalavista o 
cracks.am
, ma poi
basta, grazie. se c'e' un problema di soldi me li chiedano e
decidiamo. ma la britannica alla fine l'hanno liberalizzata...
qual e' la tecnologia valida, allora ? io continuo a pensare che
l'unica importante sia un'intelligenza che funziona. naturale :)
ciao

 l'unica importante sia un'intelligenza che funziona.
A parte il tuo condivisibile commento, come nel software, anche nella
costruzione di siti, il debug (anche quello concettuale) va affidato a terze
parti. L'autore tende sempre a pensare di aver fatto bene e anche quando
gironzola alla ricerca di problemi, lo fa con la segreta speranza di non
trovarne.
La terza parte invece gira per il tuo programma/sito proprio con la sadica
intenzione di trovarci tutti i guai, ed è proprio quello l'approccio giusto.
Ciao
*Roby*

 esempio. :-)
con google condivido pienamente la filosofia:
"immagini quando servono, e se servono, anche di 1 mb".
da google mi divide una cosa sola:
credo 15.999 computer, con sw seri :)
ciao nottambulo
a prop, uso anche televideo. non e' velocissimo, ma a volte fa:
 
http://makeashorterlink.com/?U2B1211C2
clicca, hal, clicca... :)