5

Let's say I have the following list:

var someList = new List<SomeObject>();

Which has the following entries:

SomeObject.Field

Apple
Orange
FruitBowl_Outside
Banana
Grape
FruitBowl_Inside

I would like to sort this list so that FruitBowl entries go at the bottom, and that subject to this, everything is alphabetic.

In order words:

SomeObject.Field

Apple
Banana
Grape
Orange
FruitBowl_Inside
FruitBowl_Outside
Gustavo Mori
  • 8,319
  • 3
  • 38
  • 52
Karl
  • 5,573
  • 8
  • 50
  • 73

5 Answers5

9

You can use the OrderBy() and ThenBy() methods:

var orderedList = someList.OrderBy(obj => obj.Field.StartsWith("FruitBowl_"))
                          .ThenBy(obj => obj.Field);
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 1
    @Karl: just note that LINQ solutions don't modify the source list, they simply prepare an `IEnumerable` for **lazy execution**. Whenever you access `orderedList` (in a new `foreach` method, for example), LINQ will have to sort your data again. You can add `ToList()` at the end of this expression which will create a new list, but in that case a more efficient way would be to use `List.Sort()` with a custom comparer (providing that you input list can be mutable). – vgru Jul 07 '11 at 07:17
2

You can create your own IComparer and pass it to the List.Sort method. I will post the code shortly.

        List<Record> list = new List<Record>();
        list.Add(new Record("Apple"));
         list.Add(new Record("Orange"));
        list.Add(new Record("FruitBowl_Outside"));
        list.Add(new Record("Banana"));
        list.Add(new Record("Grape"));
        list.Add(new Record("FruitBowl_Inside"));
        list.Sort(new RecordComparer());



public class Record {
    public Record(string data) {
        this.data = data;
    }
    private string data;
    public string Data {
        get { return data; }
        set {
            data = value;
        }
    }
}


public class RecordComparer : IComparer<Record> {
    public int Compare(Record x, Record y) {
        if(x.Data.Contains("FruitBowl") && !y.Data.Contains("FruitBowl"))
            return 1;
        if(y.Data.Contains("FruitBowl") && !x.Data.Contains("FruitBowl"))
            return -1;
        return x.Data.CompareTo(y.Data);
    }
}
platon
  • 5,310
  • 1
  • 22
  • 24
1

How about:

someList.OrderBy(a => a.Field.StartsWith("FruitBowl")).ThenBy(a => a.Field);
Arcturus
  • 26,677
  • 10
  • 92
  • 107
0

You can use List.Sort() with a custom compare method - see HERE.

Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
0

how about this ↓

someList.Sort(new Comparison<string>((x, y) => { return x.StartsWith("FruitBowl") ^ y.StartsWith("FruitBowl") ? (x.StartsWith("FruitBowl") ? 1 : -1) : x.CompareTo(y); }));

And with the sample ↓

static void Main(string[] args)
    {
        List<string> lstData = new List<string>()
        {
            "Apple",
            "Orange",
            "FruitBowl_Outside",
            "Banana",
            "Grape",
            "FruitBowl_Inside"
        };


        lstData.Sort(new Comparison<string>((x, y) => { return x.StartsWith("FruitBowl") ^ y.StartsWith("FruitBowl") ? (x.StartsWith("FruitBowl") ? 1 : -1) : x.CompareTo(y); }));


        foreach (string data in lstData)
            Console.WriteLine(data);

        Console.ReadLine();
    }
shenhengbin
  • 4,236
  • 1
  • 24
  • 33