2013-07-02 17 views
11

Desidero implementare una stringa personalizzata IComparer in C# e applicarla a un ComboBox.Confronto stringa personalizzata in C#

risultati effettivi

Se ho impostato Sorted proprietà s' il ComboBox al true, l'uscita è:

A 
AA 
AAA 
B 
BB 
BBB 

Cercasi Risultati

Il comportamento desiderato del algoritmo di ordinamento è il seguente (gli sviluppatori finanziari capiranno perché :)):

AAA 
AA 
A 
BBB 
BB 
B 

Domanda

E 'possibile farlo? Gli algoritmi di ordinamento sono necessari qui?

PS: Non ho bisogno di una risposta completa con il codice, ho solo bisogno di un'idea di come potrebbe essere fatto ..

EDIT

Si tratta di rating. Ho omesso qualcosa nella mia domanda. I rating devono essere ordinati in questo ordine:

XXX 
XX+ 
XX 
XX- 
X+ 
X 
X- 

con X in ('A','B','C') e 'A' > 'B' > 'C'

+2

La documentazione di ComboBox su stati msdn - "L'ordinamento è senza distinzione tra maiuscole e minuscole e in ordine alfabetico crescente". . Penso che la cosa migliore da fare sia _inserire_ gli elementi nell'ordine corretto. (Che, puoi fare chiamando OrderBy per esempio sulla collezione di elementi se è enumerabile). –

+0

È possibile dividere l'elenco in sottoliste e ordinare le sottoliste per lunghezza. – jAC

+0

È necessario eseguire qualsiasi ordine personalizzato sul livello aziendale o sul livello presentazione, a seconda delle situazioni. –

risposta

2

Assumendo questo è per il credito le classificazioni, normalmente ciò avviene con una colonna "sort sort" sulla classe CreditRating che è possibile utilizzare per ordinare l'elenco prima di assegnarlo come origine dati del menu a discesa.

Ma, una soluzione rapida (in base ai valori limitati possibili) sarebbe per ordinare la prima lettera ascendente, quindi dalla lunghezza del discendente stringa:

if(left[0] != right[0]) 
    return left[0].CompareTo(right[0]); 
else 
    return right.Length - left.Length; 

Un'altra soluzione, se si desidera un maggiore controllo sopra l'ordine è quello di creare una lista di possibili valori nell'ordine "destra" e quindi utilizzare tale per ordinare l'elenco:

public class MyComparer : IComparer<string> 
{ 
    private static readonly string[] Ratings = new [] { 
     "CC","C","CCC-","CCC","CCC+", 
     "B-","B","B+","BB-","BB","BB+","BBB-","BBB","BBB+", 
     "A-","A","A+","AA-","AA","AA+","AAA"}; 
    // reverse the order so that any strings not found will be put at the end. 

    public int Compare(string left, string right) 
    { 
     return Array.IndexOf(Ratings, right).CompareTo(Array.IndexOf(Ratings, left)); 
    } 
} 
+1

Mentre questo funziona per i dati esatti forniti, non ordinerebbe correttamente 'ABB' con' AA'. 'AA' dovrebbe andare per primo, ma con il tuo codice sarebbe secondo. Devi passare attraverso ogni personaggio in entrambe le stringhe fino a trovare una non corrispondenza o raggiungere la fine, * quindi * confrontare le lunghezze. Non puoi semplicemente confrontare il primo personaggio. – Servy

+1

@Servy è per questo che l'ho qualificato ipotizzando che i valori fossero valutazioni del credito. 'ABB' non è un rating valido. –

+0

Grazie per la tua risposta @DStanley. È davvero per i rating di credito. Ma ho omesso qualcosa nella mia domanda, che è il tasso che termina con '+' o '-'. All'inizio pensavo al tuo algoritmo, ma tenendo a mente la mia ultima osservazione, diventa più complicato. – Fares

0

Scrivi l'IComparer in modo che ci vogliono le stringhe, ma a confronto per carattere,

if A[0] == B[0] go to the next character. 
if B[1] == null or A[1] < B[1], return A < B. 
if A[1] == null or B[1] < A[1], return B < A. 
if equal...continue as needed 
6

Ecco una versione in gran parte realizzato:

public class MyComparer : IComparer<string> 
{ 
    public int Compare(string x, string y) 
    { 
     //todo null checks on input 

     var pairs = x.Zip(y, (a, b) => new { x = a, y = b }); 

     foreach (var pair in pairs) 
     { 
      int value = pair.x.CompareTo(pair.y); 
      if (value != 0) 
       return value; 
     } 


     //if we got here then either they are the same, 
     //or one starts with the other 
     return y.Length.CompareTo(x.Length); //note x and y are reversed here 
    } 
} 

Quindi questo utilizza Zip per ottenere le coppie di caratteri da ciascuna stringa corrispondente fino alla fine, restituendo il valore appropriato se non sono uguali. Se lo supera, allora una stringa inizia con l'altra. Per un confronto di stringhe tradizionali dovremmo solo confrontare le lunghezze nello stesso ordine dei parametri di input. Poiché in pratica stiamo invertendo l'ordine in base alla lunghezza, si noti che lo x e lo vengono scambiati sull'ultima riga. Ciò inverte la logica di confronto.

+0

Sembra che il richiedente abbia un 'ComboBox' di Windows Form dal momento che menziona la proprietà [' Sorted'] (http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.sorted. aspx). In quella pagina del documento si dice che l'ordinamento è in ordine alfabetico. Quindi la domanda è (anche) come potrebbe impostare la sua casella combinata per usare il tuo comparatore. Forse non può usare le stringhe per "oggetti" nella sua casella combinata? (Non ricordo tutti i dettagli di 'System.Windows.Forms.ComboBox'.) –

+0

@JeppeStigNielsen L'OP ha chiesto espressamente un'implementazione di' IComparer' che applica la logica specificata. Se non è sicuro di come applicare quel comparatore al suo caso specifico (e non ha dato alcuna indicazione di avere quel problema), allora sarebbe onestamente una domanda diversa. Se sai che è difficile impostare un comparatore personalizzato e vuoi collegare/spiegare come farlo in un commento, quindi con tutti i mezzi. – Servy

+0

Grazie per la tua risposta @Servy.Ho modificato il mio post sopra e il tuo algoritmo sembra essere inefficiente tenendo a mente ciò che ho aggiunto. – Fares