Newsgroup: it.comp.lang.visual-basic
Titolo: NET Sort con colonna ibridona: alfa/num/virg/punt

Ciao,
devo ordinare un elenco di valori
(al momento sono in una colonna di un DataTable ,
ma posso anche spostarli da lì...)
dal più piccolo al più grande;
purtroppo la colonna è alfa/numerico/virgola/puntata   :-)
cioè un po' come potrebbero essere gli abitanti di città americane
(in verità è una siglatura standard, ahimè intoccabile):
LA 7,55.6
LA 669,55.6
NY 5,67.07
CH 1,88
CH 11, 009
CH 5,98.12
come detto, vorrei ordinarle dal più piccolo al più grande
in modo che risulti
CH 1,88
CH 5,98.12
CH 11, 009
LA 7,55.6
LA 669,55.6
NY 5,67.07
il Sort del DataView fallisce, 
in pratica lo sbaglio è che mette ad esempio
il 669 più piccolo di 7
cioè me li restituisce così
LA 669,55.6
LA 7,55.6
C'è un qualche metodo/parametro/controllo/pezzo di codice
che ordini come vorrei io?
(come detto posso anche temporaneamente muovere i dati
dalle DataTable e DataView per espletare l'ordinamento...)

 dalle DataTable e DataView per espletare l'ordinamento...)
Ok, allora facciamo che li metti in un array, devi definirti la tua funzione 
di comparazione (non so se il mio sistema di comparazione è corretto, è solo 
un esempio, dacci un occhio):
' -------------
 Dim d As New DataTable
 Dim a() As String
 d.Columns.Add("sigla", GetType(String), "")
 d.Rows.Add("LA 7,55.6")
 d.Rows.Add("LA 669,55.6")
 d.Rows.Add("NY 5,67.07")
 d.Rows.Add("CH 1,88")
 d.Rows.Add("CH 11, 009")
 d.Rows.Add("CH 5,98.12")
 ReDim a(d.Rows.Count - 1)
 For i As Int32 = 0 To d.Rows.Count - 1
  a(i) = d.Rows(i).Item("sigla")
 Next
 Array.Sort(a, New SiglaComparer())
' -------------
Class SiglaComparer
 Implements IComparer(Of String)
 Public Function Compare(ByVal x As String, ByVal y As String) As Integer 
Implements System.Collections.Generic.IComparer(Of String).Compare
  If (x = y) Then Return 0
  Dim alpha1 As String = x.Substring(0, 2)
  Dim alpha2 As String = y.Substring(0, 2)
  Dim numero1 As Int32 = Int32.Parse(x.Substring(3, x.IndexOf(",") - 
3).Trim)
  Dim numero2 As Int32 = Int32.Parse(y.Substring(3, y.IndexOf(",") - 
3).Trim)
  Dim puntato1 As Decimal = Decimal.Parse(x.Substring(x.IndexOf(",") + 1), 
System.Globalization.NumberFormatInfo.InvariantInfo)
  Dim puntato2 As Decimal = Decimal.Parse(y.Substring(y.IndexOf(",") + 1), 
System.Globalization.NumberFormatInfo.InvariantInfo)
  If (alpha1 < alpha2) Then
   Return -1
  ElseIf (alpha1 > alpha2) Then
   Return 1
  End If
  If (numero1 < numero2) Then
   Return -1
  ElseIf (numero1 > numero2) Then
   Return 1
  End If
  If (puntato1 < puntato2) Then
   Return -1
  ElseIf (puntato1 > puntato2) Then
   Return 1
  End If
  ' ci arriverà mai qui?
  Return 0
 End Function
End Class
Ciao 


ho difficoltŕ nell' implemetazione dell'interfaccia
(dove non sono espertissimo...);
ho fatto:
da Aggiungi Nuovo Elemento...
ho scelto Classe
gli ho tolto
Public Class Class1
...  
End Class
e ci ho incollato il tuo
Class SiglaComparer
    Implements IComparer(Of String)
...
End Class
ma
su
Implements IComparer(Of String)
zigzaga blu la parola
String 
e dice
'System.Collections.IComparer' non ha parametri di tipo, quindi non puň
avere argomenti di tipo.
su
Public Function Compare(ByVal x As String, ByVal y As String) As Integer
Implements System.Collections.Generic.IComparer(Of String).Compare
che č tutto su una riga
zigzaga blu  le parole 
System.Collections.Generic.IComparer(Of String).Compare
e dice
L'interfaccia "System.Collections.Generic.IComparer(Of String)" non č
implementata da questa classe.
nota:
sono in una webform aspx
e questo file Class1.vb lo ha voluto mettere nella sottocartellina App_Code

 implementata da questa classe.
Per il discorso di prima: non si parla della stessa classe.
Se stai lavorando con il Fw 1.1 anzichè il 2.0 allora non hai a disposizione 
la System.Collections.Generics.IComparer<T>.
Niente di così grave, sostituisci tutto con solo 
System.Collections.IComparer, e la funzione Compare() anzichè stringhe 
accetta degli object.
Tu dentro come prima cosa farai qualcosa del tipo
Dim sx as string = TryCast(x, String)
Dim sy as string = TryCast(y, String)
e tutto il resto lavorerà su sx e sy anzichè su x e y.
Ciao
Ciao 



ho    visual studio 2005     fw 2.0    no service pack
----------
se faccio una winform la tua classe viene presa senza problemi
sulle webform no
------------
ho provato a mettere l'import
Imports System.Collections.Generics
ma lo zigzaga di verde e dice
Lo spazio dei nomi o il tipo specificato nelle importazioni
'System.Collections.Generics' non contiene alcun membro pubblico o non è
definito. Accertarsi che lo spazio dei nomi o il tipo sia definito e
contenga almeno un membro pubblico e che il nome dell'elemento importato
non utilizzi alias.
e le due vechie righe blu non vanno via
se metto quello senza generics
Imports System.Collections.IComparer
lo zigzaga blu e dice
'IComparer' per le importazioni 'System.Collections.IComparer' non si
riferisce né a uno spazio dei nomi, né a una classe, né a una struttura, né
a un'enumerazione, né a un modulo.	
modificando implements così
Implements System.Collections.IComparer(Of Object).Compare
oppure
Implements System.Collections.IComparer(Of String).Compare
sottolinea di blu Object e String e dice
'System.Collections.IComparer' non ha parametri di tipo, quindi non può
avere argomenti di tipo.
non ne esco
nota:
nelle webform comunque nel menu contestuale usato per scriver l'Imports 
i Generics ci sono

 avere argomenti di tipo.
Beh, questo è chiaro: la versione generics con (Of T) sta in 
System.Collection.Generics, quello in System.Collections è la versione 
classica.
Ciao 

Dev'essere da mscorlib.
Vai a definizione non mi apre nulla


>> definito.
Capito!
Colpa mia, ma dovresti averlo notato: il namespace si chiama 
System.Collections.Generic e non System.Collections.Generics con la "s" 
finale (mannaggia a MS!).
Comunque, piglia quanto segue e sostituiscilo a TUTTO quello che hai nella 
tua pagina di test.
' -------------
Partial Public Class _Default
    Inherits 
System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As 
System.EventArgs) Handles Me.Load
        Dim d As New DataTable
        Dim a() As String
        d.Columns.Add("sigla", GetType(String), "")
        d.Rows.Add("LA 7,55.6")
        d.Rows.Add("LA 669,55.6")
        d.Rows.Add("NY 5,67.07")
        d.Rows.Add("CH 1,88")
        d.Rows.Add("CH 11, 009")
        d.Rows.Add("CH 5,98.12")
        ReDim a(d.Rows.Count - 1)
        For i As Int32 = 0 To d.Rows.Count - 1
            a(i) = d.Rows(i).Item("sigla").ToString()
        Next
        Array.Sort(a, New SiglaComparer())
    End Sub
End Class ' -------------
' -------------
Class SiglaComparer
    Implements System.Collections.Generic.IComparer(Of String)
    Public Function Compare(ByVal x As String, ByVal y As String) As Integer 
Implements System.Collections.Generic.IComparer(Of String).Compare
        If (x = y) Then Return 0




        ' ci arriverà mai qui?


 string, comunque sia puoi scegliere tra
leggi "IComparer generica" come "IComparer normale", altrimenti facciamo 
confusione con quella in Generic.
Ciao

tua pagina di test.
fatto ed è andato tutto liscio
l'ordinamento pure sembra ordinare bene
ora lo adatto al fatto che posso avere 
i valori fino a ZZZZZ 999,999.999.999
(ma credo sia solo una questione facile di estrazione delle stringhette
con Substring)
poi non capisco come Compare ed il gioco dei  return  0,  1 , -1
riescano a determiare l'ordinamento ,  ma... non mi importa poi tanto !!
cmq come detto mi sa che ci siamo ,
bravo, grazie mille


 riescano a determiare l'ordinamento ,  ma... non mi importa poi tanto !!
Come non ti importa?
E' la base del funzionamento :)
La Compare consente alla Sort di determinare se x viene prima o dopo y.
Se restituisce -1 x viene prima, 0 x = y, se 1 x viene dopo y.
Se non gli passi una Compare personalizzata per le stringhe usa il classico 
ordinamento alfabetico.
Tutta roba scritta su MSDN ;)
Finalmente ce l'abbiamo fatta :)
Ciao 

Finalmente ce l'abbiamo fatta :)
mah il merito è tutto tuo;
io pi non sapevo implementare l'interfaccia;
mentre alla scomposizione del valore in sottostringhette
ci avevo pensato, magari non sintetica come la tua;
avevo pensato invece (e credo che avrebbe funzionato)
di riportare la stringa con uno bel Format 
tutta piena di 000 e di togliere le interpunzioni,
cioè esempio
da 
AL 99,12.4
a
AL 099,120.400.000
e infine a
AL 099120400000
a questo punto sarebbe stata più gestibile,
(dividendo comunque quasi obbligatoriamente
la parte letterale dalla parte numerica e facendo un Sort esterno pre la
letterale ed un Sort interno per i numeri)

ho XP pro con il suo sp1
no, sp2

 letterale ed un Sort interno per i numeri)
Beh, una "brutta notizia" :)
Non sapevo della struttura del codice, però se riesci a formattarlo anche 
solo così
AL 099,120.400.000
allora la Array.Sort funzionerebbe senza nessun Comparer esterno perchè il 
codice è ordinabile in modo alfabetico.
Ciao


e quello generico
http://msdn2.microsoft.com/en-us/library/2y07t0wt.aspx
Ciao