2016-03-17 31 views
8

Ho una lista di stringa contenente "Others". Sto ottenendo questa lista per la discesa. Sto ordinando alfabeticamente questa lista. Ma ho bisogno di "Others" sempre alla fine della lista. Non voglio aggiungere questo elemento dopo l'ordinamento, che è una soluzione. C'è un altro modo per fare lo stesso come utilizzando il confronto personalizzato del metodo .Sort(). Ho provato come sotto ma nessuna soluzione.ordinare un elenco e mantenere un particolare elemento alla fine della lista dopo l'ordinamento

public class EOComparer : IComparer<string> 
    { 
     public int Compare(string x, string y) 
     { 
      if (x == null) 
      { 
       if (y == null) 
       { 
        // If x is null and y is null, they're 
        // equal. 
        return 0; 
       } 
       else 
       { 
        // If x is null and y is not null, y 
        // is greater. 
        return -1; 
       } 
      } 
      else 
      { 
       // If x is not null... 
       // 
       if (y == null) 
       // ...and y is null, x is greater. 
       { 
        return 1; 
       } 
       else 
       { 
        if (x.ToLower().Contains("other")) 
        { 
         return -1; 
        } 
        else 
        { 
         // If the strings are of equal length, 
         // sort them with ordinary string comparison. 
         // 
         return x.CompareTo(y); 
        } 
       } 
      } 
     } 

e definendolo come:

EOComparer c = new EOComparer(); 
a.Sort((x, y) => c.Compare(x.OptionValue, y.OptionValue)); 
      return a; 

Si prega di aiutare se è possibile.

+0

add "se y contiene 'altro' ritorno 1" troppo – user489872

+0

Perché non utilizzare un dizionario? Metti "Altri" come chiave e la lista ordinata come valore –

risposta

10

This è una risposta bene, ma ho pensato di risolvere il tuo operatore di confronto:

prova:

[TestCase(new string[0], new string[0])] 
[TestCase(new[] { "a" }, new[] { "a" })] 
[TestCase(new[] { "a", "b" }, new[] { "a", "b" })] 
[TestCase(new[] { "b", "a" }, new[] { "a", "b" })] 
[TestCase(new[] {"others"}, new[] {"others"})] 
[TestCase(new[] {"a", "others"}, new[] {"a", "others"})] 
[TestCase(new[] {"others", "a"}, new[] {"a", "others"})] 
[TestCase(new[] {"others", "x"}, new[] {"x", "others"})] 
[TestCase(new[] {"Others", "x"}, new[] {"x", "Others"})] 
[TestCase(new[] { "othersz", "others" }, new[] { "othersz", "others" })] 
[TestCase(new[] {"z", "y", "x", "others", "b", "a", "c"}, 
      new[] {"a", "b", "c", "x", "y", "z", "others"})] 
public void CanSortWithOthersAtEnd(string[] input, string[] expectedSorted) 
{ 
    var a = new List<string>(input); 
    var c = new EOComparer(); 
    a.Sort(c.Compare); 
    CollectionAssert.AreEqual(expectedSorted, a); 
} 

Comparer:

public sealed class EOComparer : IComparer<string> 
{ 
    public int Compare(string x, string y) 
    { 
     if (IsOthers(x)) return 1; 
     if (IsOthers(y)) return -1; 
     return string.Compare(x, y, StringComparison.Ordinal); 
    } 

    private static bool IsOthers(string str) 
    { 
     return string.Compare(str, "others", StringComparison.OrdinalIgnoreCase) == 0; 
    } 
} 

Nota come il mio uso di string.Compare evita tutti i controlli == null. E come StringComparison.OrdinalIgnoreCase evita .ToLower() e quindi evita di creare copie delle stringhe.

+1

Questa è una soluzione migliore perché evita di fare una copia temporanea della lista (che farà la soluzione Linq.) Anche se la lista è piccola, questo non ha importanza .. –

+0

Ottimo .. Ha funzionato :) – Gerry

15

Utilizzare questa logica

List<string> l = new List<string>{ "z", "y", "x", "other", "b", "a", "c" }; 
var result = l.OrderBy(i => i == "other").ThenBy(i => i).ToList(); 
result.ForEach(Console.WriteLine); 

uscita:

a b c x y z altra

Se vuoi other di essere in cima alla lista rendono

var result = l.OrderBy(i => i != "other").ThenBy(i => i).ToList(); 

uscita:

altro abcxyz

+0

In realtà avevo già provato questo, ma non ha funzionato. La mia lista è una lista di oggetti con id e valore e ho provato ad esempio "l.OrderBy (i => i.Value! = "Altro"). ThenBy (i => i.value) .ToList(); "ma non funzionava per me – Gerry

+0

Non è stato risolto affatto o era" altro "no apparso nel posto giusto? – CarbineCoder

+0

ho provato con! = e == operatore ma "altro" non compariva su nessuna delle due estremità .. il risultato era lo stesso del normale orderby (valore) – Gerry

0

Supponiamo di avere oggetti con le seguenti voci di elenco.

object.Text = "a" Object.Value = 1

object.Text = "b" Object.Value = 2

object.Text = "altro" Object.Value = 3

object.Text = "c" Object.Value = 4

le seguenti opere per me:

var oList = objects.OrderBy (i => i.Text! = "Other"). ThenBy (i => i.Text);