2010-02-26 6 views
7

Mam listę obiektów, które należy sortować w zależności od trzech różnych właściwości obiektu. Przykładowa listaprzy użyciu porównywarki do sortowania IEnumerable w języku C# według różnych pól

CLass Object1{ Property1 , Property2, Property3} 

ListObj = IEnumerable<Object1> 

Foreach (item in ListObj){ 

    if (item.Property1 == true) 
     item goes at top of list 
    if(item.Property2 == true) 
     item goes end of list 
    if(item.Property3 == true) 
     item can go anywhere. 
} 

końcowy powinien być obiekty z Property1 = true następnie obiektów z Property2 = true następnie obiektów z Property3 = true

+0

Właściwie to jest trochę niejasne. Myślałem, że przedmioty z własnością 3 mogą iść gdziekolwiek? –

+0

Myślę, że mam to teraz ... Zmieniłem swoją odpowiedź poniżej, aby lepiej odzwierciedlić sytuację. –

+0

Nie jest jasne, ponieważ istnieje kwestia pierwszeństwa. Kod czyta w jedną stronę (koniec listy zastępuje przód listy), ale podejrzewam, że masz na myśli to w inny sposób (przód listy przesłania koniec listy) –

Odpowiedz

7

Dlaczego nie używać LINQ?

var orderedList = 
    ListObj.OrderByDescending(x => x.Property1) 
      .ThenByDescending(x => x.Property2); 
+0

Nie zapewnia właściwego sortowania zgodnie z wymaganiami PO. – AxelEckenberger

+1

@Obalik: Jakie jest właściwe sortowanie wskazane przez OP? Wskazuje dwie możliwości ... jego kod wskazuje na jedną możliwość, podczas gdy tekst po kodzie wskazuje na inną. A tak przy okazji, prawda przychodzi po fałszywej z prostym OrderBy. OrderByDescending sprawia, że ​​naprawdę jest na pierwszym miejscu. –

+0

Masz rację, przepraszam! – AxelEckenberger

4

Własny tytuł już mówi wszystko: wdrożenie niestandardowych IComparer<Object1> i przekazać je do metody OrderBy rozszerzenie:

var orderedItems = ListObj.OrderBy(obj => obj, customComparer); 
1

To powinno zapewnić wymaganą sortowania (według kodu, a nie komunikatu poniżej).

ListObj.Where(x => x.Property1 == true) 
     .Concat(ListObj.Where(x => x.Property1 == false && x.Property2 == false)) 
     .Concat(ListObj.Where(x => x.Property2 == true)); 
2

Można dokonać rzeczy neater dla siebie, jeśli zdefiniować ten rodzaj:

public class ComparisonComparer<T> : IComparer<T> 
    { 
     private readonly Comparison<T> _comparison; 

     public ComparisonComparer(Comparison<T> comparison) 
     { 
      _comparison = comparison; 
     } 

     public int Compare(T x, T y) 
     { 
      return _comparison(x, y); 
     } 
} 

który pozwala zdefiniować porównanie inline ze stwierdzeniem, LINQ, używając wyrażenia lambda.

1

Myślę, że chcesz zdefiniować funkcję porównania, w której możesz określić pozycję między dowolnymi 2 pozycjami na liście.

int CompareObject1(Object1 left, Object1 right) 
    { 
     // TODO: cases where your items are null 

     // compare Property1 values 
     if (left.Property1) 
     { 
      if (right.Property1) 
      { 
       // items at same rank 
       return 0; 
      } 
      else 
      { 
       // left item is higher rank than right 
       return -1; 
      } 
     } 
     else if (right.Property1) 
     { 
      // right item is higher rank than left 
      return 1; 
     } 

     // Property1 doesn't indicate position, move along 
     // TODO: repeat for Property2 

     // Property2 doesn't indicate position, move along 
     // TODO: repeat for Property3 

     // if we get here, no determination can 
     // be made/don't bother to move anything 
     return 0; 
    } 

Wartość zwracana wskazuje, czy lewy czy prawy obiekt powinien mieć wyższą pozycję z -1 lub 1 (lub 0 dla preferencji). po prostu upewnij się, że pokrywasz wszystkie swoje warunki.

następnie można użyć to jak

List<Object1> foo = new List<Object1>() { <items...> }; 
foo.Sort(CompareObject1); 

jeśli lista kończy się wstecz, pewnie odwrócona znaki w funkcji porównania. twoje zasady sortowania są sprzeczne, więc pozwolę ci posortować Property2 i Property3.

Powiązane problemy