2015-12-08 65 views
5

La mia tabella di dati contiene tutte le colonne di stringhe ma in alcune colonne stiamo riempiendo i valori numerici. quando ordino su datatable di quella colonna numerica, non sta ordinando correttamente. prima che l'ordine mio tavolo sembraConverti in decimale e fai l'ordine con

Name Account Department 
Kiran 1100 CSC 
Subbu 900  CSC 
Ram  500  CSC 
Raj  800  CSC 
Joy  400  CSC 

dopo ordine sembra

Name Account Department 
Kiran 1100 CSC 
Joy  400  CSC 
Ram  500  CSC 
Raj  800  CSC 
Subbu 900  CSC 

Il mio codice:

public DataTable sortData(string columnName) 
{ 
    DataTable dt1=new DataTable(); 
    return dt1=dataMgr[DatabaseFileNames.ControlDatabase]["OrderedTableName"] 
       .Select("Department='CSC'") 
       .OrderBy(x=>!string.IsNullOrEmpty(x.Field<string>(columnName))) 
       .CopyToDataTable(); 
} 
+0

Nel tuo esempio, cosa stai passando per 'columnName'? Inoltre, la colonna 'Account' è una colonna numerica o no? – Jamiec

+1

la mia tabella potrebbe contenere anche valori vuoti. –

+0

@MarcoForberg che dice "datatable" - Im chiedendo la fonte dei dati - il database. – Jamiec

risposta

1

ho pensato a questo po 'di tempo e la soluzione mi è venuta è incredibilmente evidente: Essenzialmente l'ordinazione è tutto a confronto - così perché non solo scrivere un costume Comparer ...

public class MyComparer : IComparer<string> 
{ 
    private readonly string _columnName; 
    public MyComparer(string columnName) 
    { 
     _columnName = columnName; 
    } 

    public int Compare(string leftValue, string rightValue) 
    { 
     double leftDouble, rightDouble; 

     switch (_columnName) 
     { 
      case "Account": 
       if (Double.TryParse(leftValue, out leftDouble) && Double.TryParse(rightValue, out rightDouble)) 
       { 
        return leftDouble.CompareTo(rightDouble); 
       } 
       else 
       { 
        return String.Compare(leftValue, rightValue); 
       } 
      default: 
       return String.Compare(leftValue, rightValue); 
     } 
    } 
} 

... e poi semplicemente aggiungerlo al OrderBy ...

public DataTable sortData(string columnName) 
{ 
    DataTable dt1=new DataTable(); 
    return dt1=dataMgr[DatabaseFileNames.ControlDatabase]["OrderedTableName"] 
       .Select("Department='CSC'") 
       .OrderBy(x => x.Field<string>(columnName) ?? String.Empty, 
          new MyComparer(columnName) 
        ) 
       .CopyToDataTable(); 
} 

... e abbiamo finito e può anche estendere tale soluzione di utilizzare altri tipi di dati ad esempio DateTime.

+0

Grazie Marco, la tua soluzione sta funzionando per tutti i miei scenari .. –

3

tuo OrderBy dovrebbe guardare un po 'come questo:

.OrderBy(x => double.Parse(x.Field<string>(columName))) 

Di co urse che presuppone che tutti i tuoi valori siano effettivamente analizzabili come double.

Se è necessario farlo funzionare anche per le colonne non numeriche, non penso che dovrete evitare di dover differenziare in base al nome della colonna. (I. e che avrebbe dovuto avere qualche mappatura tra columnName ed un IComparer..)

che potrebbe sembrare un po 'come questo:

IComparer comparer = null; 
// instead of a switch/case you could also have a Dictionary<string, IComparer> for example... 
switch(columName) 
{ 
    case "Account": comparer = Comparer<double>.Default; 
        break; 
    default: comparer = Comparer<string>.Default; 
        break; 
} 

// so your OrderBy would look like this: 
.OrderBy(x => x, comparer) 

La soluzione più pulita sarebbe sicuramente avendo i dati corretti tipi per le colonne nella tabella.

+2

Attenzione. Il nome dell'ordine per colonna viene passato a questo metodo come parametro, quindi potrebbe anche essere la colonna nome –

+0

@MarcoForberg Appena notato che hai ragione.L'utente – germi

+0

può passare anche la colonna "Nome" .. il codice dovrebbe funzionare per tutte le colonne –

2

Si può semplicemente pad string contenente int valore con i principali 0 per l'ordinamento per funzionare correttamente:

.OrderBy(x => x.Field<string>(columnName)?.PadLeft(10, '0') ?? "0") 

Si dovrà definire dimensioni di essere abbastanza grande (10?) E qualche valore per null di risolverlo come preferisci (in caso di utilizzo di "0" verranno visualizzati per primi).

+0

Questo è intelligente, non ci ha pensato. Anche se avrai problemi con le colonne non numeriche. – germi

+0

Idea intelligente, ma temo che ciò causerà problemi se i dati devono essere ordinati per Nome –

+1

@MarcoForberg, per i valori negativi o per i numeri a virgola mobile anche questo non funzionerà. Ma l'idea dovrebbe essere chiara e spetta a OP decidere se usarla o meno. – Sinatr