Newsgroup: it.comp.lang.visual-basic
Titolo: Esiste un qualche "santone" del VB in grado di aiutarmi ?

Innanzi tutto grazie di aver aperto questo messaggio.
Dunque, il mio problema č questo: supponiamo di avere una tabella con
i seguenti valori (inventati):
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
A	0	3	0	2	1	1	0
B	1	2	1	0	2	2	0
C	1	1	1	0	0	0	0
D	1	1	1	0	0	0	0
E	0	2	0	2	1	1	0
F	0	2	1	0	2	2	0
... a me servirebbe una funzione, un'istruzione SQL, una magia,
un'imprecazione speciale, che li ordini in questo modo:
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
C	1	1	1	0	0	0	0
D	1	1	1	0	0	0	0
B	1	2	1	0	2	2	0
F	0	2	1	0	2	2	0
A	0	3	0	2	1	1	0
E	0	2	0	2	1	1	0
...ovvero ordinati a seconda della "similitudine" (non trovo altri
termini per spiegarlo) tra i vari record, PARTENDO DA DESTRA A
SINISTRA; infatti si nota come i primi due record (C e D) siano
"uguali", B e F sono uguali per 6/7... A ed E sono uguali per 5/7, e
cosě via...
Se ti occorrono ulteriori informazioni, rispondi sul NG o direttamente
alla mia mailbox (devi cancellare "_toglimi_" dall'indirizzo).
Non so come raccapezzarmi, ogni aiuto puň essere prezioso...
Grazie ancora
Wolf
"Lo stress č quell'apostrofo grigio tra le parole...M'INCAZZO"

 cosě via...
Prima osservazione: A ed E sono uguali a 6/7 e non 5/7!
Se ho capito bene, ti posso tranquillizzare. E' IMPOSSIBILE FARLO!
Prendi per esempio una tabella come questa
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
A	1	1	1	2	0	2	0
B	1	1	1	0	2	2	0
C	1	1	1	0	0	2	0
D	1	1	1	0	2	0	0
E	1	1	1	0	0	0	0
Tu come la ordineresti?
Cosi':
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
D	1	1	1	0	2	0	0
B	1	1	1	0	2	2	0
A	1	1	1	2	0	2	0
C	1	1	1	0	0	2	0
E	1	1	1	0	0	0	0
Oppure cosi':
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
E	1	1	1	0	0	0	0
D	1	1	1	0	2	0	0
B	1	1	1	0	2	2	0
C	1	1	1	0	0	2	0
A	1	1	1	2	0	2	0
Dimmi te come andrebbe ordinata questa tabella.....
Secondo me non ci riesci. Ammeno che non ti inventi qualche regola
in piu'.
-- 
Hi, Ciao
Ettore                 By -MES-
http://freeweb.aspide.it/freeweb/ilmes
Il sito comune di programmatori VB
http://members.xoom.com/it_lang_vb

Hi, Ciao
Ciao Ettore e grazie


 
Ok, adesso e' chiaro, e forse ho la soluzione.
Attento che e' un bel casino.....
1) crea un nuovo archivio access
2) nell'archivio crea 3 tabelle
	Tabella 1:
	Nome=Tabella
	Campi:
		ABC	tipo testo
		L1	tipo numerico
		L2	tipo numerico
		L3	tipo numerico
		L4	tipo numerico
		L5	tipo numerico
		L6	tipo numerico
		L7	tipo numerico
	Tabella 2:
	Nome=TabCalcoloPesi
	Campi:
		ABC	tipo testo
		Pesi	tipo numerico
	Tabella 3:
	Nome=TabMaxPesi
	Campi:
		ABC	tipo testo
		Pesi	tipo numerico
Riempi la tabella "Tabella" con questi valori:
ABC	L1	L2	L3	L4	L5	L6	L7
----------------------------------------------------------
A	1	1	1	2	0	2	0
C	1	1	1	0	2	2	0
B	1	1	1	0	0	2	0
D	0	0	0	1	2	3	4
E	0	0	0	2	2	3	4
F	0	0	0	1	0	3	4
Crea un nuovo progetto, aggiungi nel form un DataContro, ed un DBGrid collegato
al DataControl.
Nel Form Load Scrivi:
Private Sub Form_Load()
    Dim db As Database
    Dim ClausuleJoin$, Join$, SQL$
    Dim Peso%
 
    Set db = OpenDatabase("d:\t\delme\db1.mdb", False, False)
 
    'Cancello la tabella usata per ricavare i pesi
    db.Execute "DELETE * FROM TabCalcoloPesi"
 
    'Cancello la tabella usata per ricavare la somma dei pesi
    db.Execute "DELETE * FROM TabMaxPesi"
 
    '
    ' Creo i pesi nelle 7 possibili combinazioni tra i campi L1..L7
    ' ossia conto quanti record sono uguali tra di loro per:
    ' L7, L7+L6, L7+L6+L5, L7+L6+L5+L4, L7+L6+L5+L4+L3, L7+L6+L5+L4+L3+L2, L7+L6+L5+L4+L3+L2+L1
    ' e metto tutti i rusultati nella tabella "TabCalcoloPesi"
    '
    ClausuleJoin$ = "(Tabella.L7 = TX.L7)|(Tabella.L6 = TX.L6)|(Tabella.L5 = TX.L5)|(Tabella.L4 = TX.L4)|(Tabella.L3 =
TX.L3)|(Tabella.L2 = TX.L2)|(Tabella.L1 = TX.L1)|"
    Peso% = 1
    Do
        If Len(ClausuleJoin$) = 0 Then Exit Do
        If Len(Join$) Then Join$ = Join$ & " AND "
        Join$ = Join$ & Left$(ClausuleJoin$, InStr(ClausuleJoin$, "|") - 1)
        ClausuleJoin$ = Mid$(ClausuleJoin$, InStr(ClausuleJoin$, "|") + 1)
        SQL$ = "INSERT INTO TabCalcoloPesi ( ABC, Pesi ) SELECT Tabella.ABC, iif(Count(Tabella.ABC)>1,1,0)*" & Peso% & " AS
Pesi FROM Tabella INNER JOIN Tabella AS TX ON " & Join$ & " GROUP BY Tabella.ABC;"
        db.Execute SQL$
        Peso% = Peso% + 1
    Loop
    '
    ' Calcolo i Massimi dei pesi
    '
    db.Execute "INSERT INTO TabMaxPesi ( ABC, Pesi ) SELECT TabCalcoloPesi.ABC, Max(TabCalcoloPesi.Pesi) AS Pesi From
TabCalcoloPesi GROUP BY TabCalcoloPesi.ABC;"
 
    '
    ' E questa è la SQL che da la lista ordinata come tu desideri
    '
    Data1.RecordSource = "SELECT Tabella.* FROM Tabella INNER JOIN TabMaxPesi ON Tabella.ABC = TabMaxPesi.ABC ORDER BY
TabMaxPesi.Pesi DESC , Tabella.L1 DESC , Tabella.L2 DESC , Tabella.L3 DESC , Tabella.L4 DESC , Tabella.L5 DESC , Tabella.L6
DESC , Tabella.L7 DESC;"
    Data1.DatabaseName = db.Name
    Data1.Refresh
 
End Sub
Informami se la soluzione puo' andare bene.
(se funziona mi devi una Birra bella fresca)
Salutoni e .... Buona Fortuna  :-))


cosě via...
Allora, via SQL scordatelo perche non si puo' fare. Puoi pero ordinare
con un algoritmo in cui ti scorri due recordset e li confronti a
coppie per stabilire quale record viene prima e quale dopo. Ti
memorizzi poi il risultato in una stringa in modo da avere alla fine
una cosa tipo "CDBFAE" che costituisce l'ordinamento cercato. Lo so,
e' lento da morire (e per di piu' ha una complessita' esponenziale),
ma secondo me e' l'unica soluzione.
Ciao
shrike

SINISTRA; infatti si nota come i primi due record (C e D) siano
oh, senti, non che io abbia in mente una soluzione precisa, ma intanto
parliamone.
come scegli il primo record?  in modo arbitrario?  oppure vedi quali
sono i due record piu' "simili" tra loro e li metti in cima, e poi gli
altri a seguire?
poi, metti caso che tu abbia due coppie di record con uguale "indice
di similitudine".  quale metti per prima?  anche perche' bisogna
considerare che la "regola" con cui valuti la similitudine (il
paragone col record precedente) varia record per record, e mettere una
invece che l'altra coppia potrebbe portare ad ordinamenti diversi.
tu potresti dire, valuto l'ordinamento che mi da', record per record,
l'indice di similitudine in media piu' alto...
ad occhio direi che non e' impossibile ma che non si puo' fare tutto
in una volta.  quello che farei sarebbe di valutare tutte le possibili
permutazioni "promettenti", record per record confrontarli e sommare i
punteggi di similitudine e farne una media.
si', proprio una ricerca esaustiva basata sulla forza bruta...
credo che abbia a che fare con gli alberi o la genetica qc del genere,
io non ho studiato queste cose ma altri sicuramente si' e magari
potrebbero dire se la mia non e' un'idea del tutto peregrina.
su quanti record devi lavorare?
======================================================
my opinions do not necessarily have to be true.
======================================================
per rispondermi rimuovere NOSPAM. dall'indirizzo email
to answer me remove NOSPAM. from email address
======================================================

su quanti record devi lavorare?
diciamo 30/40 al massimo
Saluti
Wolf
"Lo stress è quell'apostrofo grigio tra le parole...M'INCAZZO"

diciamo 30/40 al massimo
ok, allora, trovare la prima coppia dovrebbe essere facile: per ogni
record controllo l'indice di similitudine con tutti gli altri 39,
quindi ho 40x40=1600 circa controlli, che e' ancora ragionevole.
(anzi, pure meno di 1600 perche' se controlli il quinto col decimo non
andrai a ricontrollare il decimo col quinto, mo' nun me ricordo come
si chiama sta cosa, mi pare permutazione senza ripetizione, boh, c'e'
anche una formula che ti dice quanti controlli farai).
ottengo la coppia dei due record piu' simili.  pero' anche qui, se i
record non sono uguali, quali metti per primo?
ok, stabilito quale metti per primo e anche quale per secondo,
applichi lo stesso metodo, ovvero confronti il secondo con tutti i
record meno il primo, trovi il terzo e cosi' via.
ma questo lo sapevi gia', suppongo.
potremmo vedere come definire questo "indice di similitudine" e farne
una funzione.  suppongo che tu sia pratico del concetto di recordset e
field.
diciamo che settiamo un recordset sulla tabella dove hai i tuoi circa
40 record.
questo recordset avra' un elenco di fields, i campi dei record.
questi field ce li possiamo enumerare in un ciclo con due sistemi:
dim rst as recordset
dim fld as field
for each fld in rst.fields
  ' fai qualcosa
next fld
oppure:
dim rst as recordset
dim fld as field
dim i as integer
for i=0 to rst.fields.count-1
  ' fai qualcosa
next i
(a me piace di piu' il for each, pero' leggo che in alcune situazioni
estreme, tipo compilazione di activex, puo' dare dei problemi -
sicuramente non nel nostro caso.  comunque se ti interessa leggiti il
mex "Baco mostruoso o cosa??? (lunghetto)" su questo ng).
ora proviamo a fare questa funzione che restituisce l'indice di
similitudine.  gli dobbiamo ovviamente passare due record.  anche qui
le possibilita' sono diverse: gli passiamo i due record sotto forma di
array (vettore)?  oppure gli passiamo un recordset e due puntatori?
col recordset e' piu' facile scrivere il codice, ma il codice stesso
risulta meno usabile.  forse in questo caso conviene passare due
array.  quindi facciamo conto che in arr1 e in arr2 abbiamo due record
da confrontare, i valori dei campi saranno gli elementi dell'array:
public function fsimil(arr1(), arr2()) as integer 
dim i as integer
dim simil as integer
for i=ubound(arr1) to ubound(arr1)
  simil=simil+abs(arr1(i)-arr2(i))
next i
fsimil=simil
end function
campo per campo faccio la differenza assoluta tra un campo e l'altro e
la sommo nella variabile simil.  dopo aver scorso tutti i campi avro'
un certo valore in simil.  piu' e' *basso* (meno differenze ho
riscontrato tra i campi), piu' i due record si assomigliano.
se fin qui il discorso ti fila direi che non dovrebbe essere difficile
continuare.
dim rst as recordset
dim arr1()
dim arr2()
dim i as integer ' (tanto abbiamo detto max 40 record)
dim j as integer
dim bestsimil as integer ' (32000 e rotti dovrebbe bastare...)
dim tempsimil as integer
dim jsimil as integer
set rst=...(lo sai tu)
rst.movelast
rst.movefirst
bestsimil=32767
' il massimo valore per un integer.  questo perche' 
' i valori di similitudine *migliori* sono i piu' bassi.
for i=1 to rst.recordcount
  rst.movefirst
  rst.move i
  ' scrivo in qualche modo i campi in arr1()
  for j=1 to rst.recordcount-i
  ' ovvero scorro dal record successivo a quello in esame all'ultimo
    rst.movefirst
    rst.move j
    ' scrivo in qualche modo i campi in arr2()
    tempsimil=fsimil(arr1(), arr2())
    if bestsimil<tempsimil then
    ' (capito perche' bestsimil=32767 all'inizio?)
      bestsimil=tempsimil
      jsimil=j
    end if
  next j
  ' a questo punto hai ottenuto, dato un i-esimo record, qual e' il 
  ' j-esimo che gli e' piu' "simile".
next i
ovviamente quanto sopra e' solo un abbozzo, magari se siamo sulla
direzione giusta si puo' proseguire, fammi sapere, ogni tanto mi
appassionano questi thread-saga... :-)


appassionano questi thread-saga... :-)
pant, pant =8-P
Provo ad implementare il tuo codice, ma ho paura che sia simile a
quello che avevo già scritto in prima battuta (e che non funzia ! :-(
). Se hai bisogno di altri chiarimenti, fammelo sapere... Se non
riesco a finire 'sta routine, non vado in ferie tranquillo ;-)
Per il momento grazie !
