using Comparer to sort IEnumerable in C# by different fields
Asked Answered
Z

5

8

I have a list of an object which need to be sorted depending on three different properties of the object. Example

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

End list should be objects with Property1 = true followed by objects with Property2 = true followed by objects with Property3 = true

Zonda answered 26/2, 2010 at 21:53 Comment(4)
Actually, this is a little unclear. I thought the items with property3 can go anywhere?Fallacious
I think I got it now... I changed my answer below to reflect the situation better.Fallacious
It is unclear, because there's a question of precedence. The code reads one way (end of the list overrides front of the list), but I suspect you mean it the other way (front of the list overrides end of list)Zita
The order of the objects with property3 as true does not matter, but objects with Property1 should always go before Property2Zonda
F
8

Why not use LINQ?

var orderedList = 
   ListObj.OrderByDescending(x => x.Property1)
          .ThenByDescending(x => x.Property2);
Fallacious answered 26/2, 2010 at 21:57 Comment(1)
@Obalix: What is the right sorting indicated by the OP? He indicates two possibilities... his code hints at one possibility, while the text after his code indicates another. And by the way, true comes after false with a simple OrderBy. OrderByDescending makes true come first.Fallacious
H
8

Your own title already says it all: implement a custom IComparer<Object1> and pass it to the OrderBy extension method:

var orderedItems = ListObj.OrderBy(obj => obj, customComparer);
Holliehollifield answered 26/2, 2010 at 21:59 Comment(0)
F
3

You can make things neater for yourself if you define this type:

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

Which lets you define the comparison inline with the LINQ statement using a lambda expression.

Forebode answered 26/2, 2010 at 22:31 Comment(0)
B
1

This should provide the required sorting (according to the code, not the statement below).

ListObj.Where(x => x.Property1 == true)
       .Concat(ListObj.Where(x => x.Property1 == false && x.Property2 == false))
       .Concat(ListObj.Where(x => x.Property2 == true));
Blasphemy answered 26/2, 2010 at 22:2 Comment(0)
C
1

i think you want to define a comparison function where you can determine rank between any 2 items in the list.

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

the return value indicates if the left or right object should be ranked higher with -1 or 1 (or 0 for preference). just make sure you cover all your conditions.

then you can use this like

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

if you're list ends up backwards, i probably flipped the signs in the compare function. your rules for sorting are contradictory so i'll let you sort Property2 and Property3.

Cambric answered 26/2, 2010 at 22:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.