2016-03-17 24 views
8

Mam listę ciągów zawierających "Others". Otrzymuję tę listę do rozwijania. Sortuję tę listę alfabetycznie. Ale potrzebuję "Others" zawsze na końcu listy. Nie chcę dodawać tego elementu po sortowaniu, co jest jednym z rozwiązań. Czy jest jakikolwiek inny sposób, aby zrobić to samo jak przy użyciu niestandardowego porównywalnika metody .Sort(). Próbowałem jak poniżej, ale bez rozwiązania.Sortowanie listy i zachowanie określonego elementu na końcu listy po sortowaniu

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); 
        } 
       } 
      } 
     } 

i nazywając ją jako:

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

Proszę o pomoc, jeśli jest to możliwe.

+0

dodaj "jeśli y zawiera" inny "powrót 1" też – user489872

+0

Dlaczego nie używać słownika? Umieść "Inne" jako klucz i posortowaną listę jako wartość –

Odpowiedz

10

This jest w porządku odpowiedź, ale myślałem, że chciałbym naprawić porównywarka:

test:

[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); 
} 

porównywarka:

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; 
    } 
} 

Należy pamiętać, że moje korzystanie z string.Compare pozwala uniknąć wszystkich czeków przeprowadzanych pod numerem == null. I jak uniknąć StringComparison.OrdinalIgnoreCase unika się tworzenia kopii ciągów.

+1

Jest to lepsze rozwiązanie, ponieważ unika tworzenia tymczasowej kopii listy (co zrobi rozwiązanie Linq). Chociaż lista jest niewielka, nie ma to większego znaczenia –

+0

Świetnie .. Udało się :) – Gerry

15

Funkcja ta logika

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); 

wyjściowa:

a b c X Y Z drugiej

Jeśli chcesz other być na szczycie listy sprawiają, że

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

wyjściowa:

inne abcxyz

+0

Właściwie już to wypróbowałem, ale nie działało. Moja lista to lista obiektów posiadających id i value i próbowałem jak "l.OrderBy (i => i.Value! = "Other"). ThenBy (i => i.value) .ToList(); "ale to nie działało dla mnie – Gerry

+0

Czy nie było sortowane w ogóle lub było" inne "nie pojawiające się w odpowiednim miejscu? – CarbineCoder

+0

próbowałem z operatorem! = i == ale "inny" nie pojawił się na żadnym końcu .. wynik był taki sam jak w normalnym porządku (wartość) – Gerry

0

Załóżmy, że mamy obiekty z następującymi elementami listy.

object.Text = "A" object.Value = 1

object.Text = "B" object.Value = 2

object.Text = "inne" object.Value = 3

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

następujące prace dla mnie:

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