user857521
user857521

Reputation:

Sort List without creating new variable

I'm attempting to use Enumerable.OrderBy to sort a List because ultimately I want to be able to sort by more than a single field. At the moment it only appears to work if I create a new variable var to hold the results view which means (I think) the types need to be re-cast.

Is there a method to sort a List by more than 1 field whilst retaining the original List variable and types? I.e. I'd rather end up with variable _orderedbins of type List<orderedbins>

Below is what I currently have but everything from var test = ... onwards seems a bit wrong.

public class orderedBins
{
    public string Bin { get; set; }
    public int Order { get; set; }
}

List<orderedbins> _orderedbins = new List<orderedbins>();
foreach (string item in splitbins)
{
    string[] spbinSetting = item.Split(',');
    bool bchecked = bool.Parse(spbinSetting[1]);
    int border = int.Parse(spbinSetting[2]);

    if (bchecked == true)
    {
        _orderedbins.Add(new orderedbins { bin = spbinSetting[0], Order = border });
    }
}

var test =_orderedbins.OrderBy(x => x.Order);
foreach (var item in test)
{
   string f = item.Bin;
   int g = item.Order;
}

Upvotes: 6

Views: 5030

Answers (5)

Fung
Fung

Reputation: 3558

As others suggested, using Linq's OrderBy(...).ToList() would be a cleaner way, but this will give you a new instance of the list.

To retain the original instance, consider to use List<T>.Sort():

_orderedbins.Sort(new Comparison<orderedBins>((obj1, obj2) =>
{
    int result = obj1.Order.CompareTo(obj2.Order);
    return result != 0 ? result : obj1.Bin.CompareTo(obj2.Bin);
}));

Upvotes: 4

Servy
Servy

Reputation: 203844

You can create a new sorted list without creating a new variable using

list = list.OrderBy(item => item.Field1).ThenBy(item => item.Field1).ToList();

It will still create an entirely new list though (it's not actually much of a problem to add a new variable; those are cheap. Creating a new list, doing this, is fine as long as the list isn't very large.

If you need to sort the list in place then you'll want to use a custom comparer with the List's sort method:

public class MyComparer : IComparer<MyClass>
{

    public int Compare(MyClass x, MyClass y)
    {
        if(x.Field1 != y.Field1)
            return x.Field1.CompareTo(y.Field1)
        else
            return x.Field2.CompareTo(y.Field2);
    }
}

List<MyClass> list = new List<MyClass>();
//Populate list

list.Sort(new MyComparer());

Upvotes: 4

Christopher Bales
Christopher Bales

Reputation: 1071

I think this will do it (it's already a list of orderbins so no casting is required):

_orderbins = _orderbins.OrderBy(x => x.Order).ToList();

Upvotes: 1

YoryeNathan
YoryeNathan

Reputation: 14522

You know, you can perform multiple sub-sorts for an order by...

lst.OrderBy(x => x.Prop1).ThenBy(x => x.Prop2).ThenByDescending(x => x.Prop3)...

Just add a .ToList(); and introduce it with a variable, to have the result in a list variable.

EDIT:

Great suggestion by Willem, for more readability:

from x in lst
order by x.Prop1, x.Prop2, x.Prop3
select x

Upvotes: 5

Kieren Johnstone
Kieren Johnstone

Reputation: 42013

This will do the trick:

_orderedbins = _orderedbins.OrderBy(x => x.Order).ToList();

...but there's no real issue creating a new variable/reference.

Upvotes: 3

Related Questions