I am currently ordering a list of custom objects using the IQueryable OrderBy method as follows:
mylist.AsQueryable().OrderBy("PropertyName");
Now I am looking to sort by more than one property. Is there any way to do that?
Thanks,
Yannis
OrderBy(i => i.PropertyName).ThenBy(i => i.AnotherProperty)
In OrderBy and ThenBy you have to provide keySelector function, which chooses key for sorting from object. So if you know property name only at runtime then you can make such function with Reflection like:
var propertyInfo = i.GetType().GetProperty("PropertyName");
var sortedList = myList.OrderBy(i => propertyInfo.GetValue(i, null))
But it will be slower, then direct access to property. Also you can "compile" such function on the fly with Linq.Expressions and it will work faster than reflection but it is not very easy. Or you can use CollectionViewSource and their sorting ablilities in WPF.
And don't forget that OrderBy() returns sorted enumerable and it does not sort your existed List inplace. In your example you did not save sorted list to variable.
You could use .ThenBy:
var result = mylist
.AsQueryable()
.OrderBy(x => x.PropertyName)
.ThenBy(x => x.SomeOtherProperty);
You probably want to use the ThenBy extension method to be able to sort by multiple fields
return myList.AsQueryable().OrderBy(m=>m.Property1).ThenBy(m => m.Property2);
If you want dynamic Linq, look at LinqKit. I recently implemented Microsoft's dynamic Linq library from here and was able to sort by two fields using a string.
Awesome stuff! Not sure if this will be in .NET 5 or not.
As others have suggested, you can use 'ThenBy'. If you want to convert a string to a different value before using it, this is possible too, for example...
var sortedSystemTestResultsList = systemTestResultsList.OrderBy(s =>
{
DateTime dt;
if (!DateTime.TryParse(s.testPointCompletedDate, out dt)) return DateTime.MaxValue;
return dt;
}).ThenBy(s =>
{
Int32 tpID;
if (!Int32.TryParse(s.testRunResultID, out tpID)) return Int32.MaxValue;
return tpID;
});
Related
I need do a filter that request data with a parameter included in a list.
if (filter.Sc.Count > 0)
socios.Where(s => filter.Sc.Contains(s.ScID));
I try on this way but this not work, I tried also...
socios.Where( s => filter.Sc.All(f => f == s.ScID));
How I can do a filter like this?
socios.Where(s => filter.Sc.Contains(s.ScID));
returns a filtered query. It does not modify the query. You are ignoring the returned value. You need something like:
socios = socios.Where(s => filter.Sc.Contains(s.ScID));
but depending on the type of socios the exact syntax may be different.
In addition to needing to use the return value of your LINQ .Where(), you have a potential logic error in your second statement. The equivalent logic for a .Contains() is checking if Any of the elements pass the match criteria. In your case, the second statement would be
var filteredSocios = socios.Where( s => filter.Sc.Any(f => f == s.ScID));
Of course if you can compare object-to-object directly, the .Contains() is still adequate as long as you remember to use the return value.
How to sort a list in C# with secondary sorting.
For example if I have a class called Student with two fields FirstName and LastName.
Until now I've sorted the list as follows:
MyStudents.Sort((s1, s2) => s1.LastName.CompareTo(s2.LastName));
I wanted to know how can I sort the list first by last name and then by first name.
Thanks.
Sort doesn't have that capability.
Linq can do this simply:
MyStudents.OrderBy(s => s.LastName).ThenBy(s => s.FirstName)
Ensure you are using at least .NET 3.5 and have the System.Linq namespace referenced.
You can use LINQ:
MyStudents.OrderBy(e => e.LastName).ThenBy(e => e.FirstName);
You can use OrderBy and ThenBy
var sortedList = MyStudents.OrderBy(s => s.LastName).ThenBy(s=> s.FirstName);
note that OrderBy and ThenBy does not change the order of MyStudents list and they return an IEnumerable<Student>, so if you need a List<Student> use ToList().
So I have this C# list:
List<DatsWussup.Models.JQGridMessage> gridMessages = new List<DatsWussup.Models.JQGridMessage>();
Each JQGridMessage has a property called age. What's the quickest and most efficient way to sort this list by age (youngest first). Age is an int.
Thanks!
The List<T> class has a Sort method which can be used to in place sort the data. One overload takes a Comparison delegate that can be implemented via an anonymous function. For example
gridMessages.Sort((x, y) => x.Age.CompareTo(y.Age));
Use Linq:
var sortedEnumerable = gridMessages.OrderBy(m => m.Age);
This will return a new IEnumerable sorted by age.
gridMessages.Sort((m1, m2) => m1.Age.CompareTo(m2.Age));
Can you use:
gridMessages = gridMessages.OrderBy(x => x.age).toList();
I have a list of objects. That objects have various field, e.g. age and name
Now sometimes I'd like to sort the list by names and sometimes by age. Additional sometimes increasing order and sometimes decreasing order.
Now I understand that i should implement the Comparable interface in my object and override the CompareTo method.
But how can i do this when i want to support various sorting orders?
Do i have to set the sorting order in my object or is it somehow possible to pass the sorting order by the sort method call?
The method call can do everything; no need for a comparer:
list.Sort((x,y)=>string.Compare(x.Name,y.Name));
list.Sort((x,y)=>y.Age.CompareTo(x.Age)); // desc
list.Sort((x,y)=>x.Age.CompareTo(y.Age)); // asc
Note the second is descending, by swapping x/y in the compare.
If you're using List<T> and you want to sort the list in place, then the Sort function provides an overload that accepts a Comparison<T>. You can use this to provide different comparisons for a list.
For example, to sort on Age:
list.Sort((x, y) => x.Age.CompareTo(y.Age));
To sort on Name:
list.Sort((x, y) => string.Compare(x.Name, y.Name));
To sort in descending order, simply reverse the parameters.
Alternatively, you could use LINQ to create various queries against your list that provide the results in whatever order you like, but this won't have any effect upon the underlying list (whether that's bad or good is up to you):
var byAge = list.OrderBy(x => x.Age);
var byName = list.OrderBy(x => x.Name);
To sort in descending order, use OrderByDescending in place of OrderBy.
You can also just use LINQ to handle this:
var sortedByAge = myList.OrderBy(i => i.Age);
var sortedByName = myList.OrderBy(i => i.Name);
If you want to handle sorting in place, you can use List<T>.Sort(Comparison<T>):
// Sort by Age
myList.Sort( (l, r) => l.Age.CompareTo(r.Age) );
// Sort by Name
myList.Sort( (l, r) => l.Name.CompareTo(r.Name) );
You can sort your objects data with linq
something like this
var query = from cust in customers
orderby cust.Age ascending
select cust;
You can also use
list.OrderByDescending(a => a.Age);
or
list.OrderByAscending(a => a.Age);
Here is my query -
var data = Goaldata.GroupBy(c => c.GoalId).ToList();
This returns a Igrouping object and I want an Iqueryable object which I can directly query to get the data while in this case I have to loop through using a foreach() and then get the data. Is there another way to group by in LINQ which returns directly as a list of Iqueryable or a List as similar to what happens for order by in LINQ.
The easiest way is probably
var data = Goaldata.GroupBy(c => c.GoalId).SelectMany(c => c).ToList();
In the OO sense they aren't really grouped, but they are ordered with the groups together.
Whilst the accepted answer is correct, it seems to be unnecessarily complicated. Assuming GoalId is an int you can just use OrderBy:
var data = Goaldata.OrderBy(c => c.GoalId).ToList();
Or .GroupBy(c => c.GoalId).AsQueryable()...