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();
Related
MyObject()
{
String dept;
List<int> id;
Object obj;
}
Using LINQ, how can I return a list of the above objects organized as follows:
Group all of the obj objects by [ department and EQUAL id list ]. The list being considered equal if it contains the same numbers, not necessarily the same order(a set).
GroupBy has an overload that accepts a custom IEqualityComparer<MyObject>. Write one that regards two objects as equal when dept is equal and id is set-equal, and pass it as an argument.
A convenient way to implement set equality is to write
new HashSet(x.id).SetEquals(new HashSet(y.id))
although this will end up being inefficient and probably not the best idea if there are lots of comparisons to make.
Building off of Jon's answer, if efficiency is an issue, you can store the HashSet for each object in an anonymous object:
myObjects.Select(x => new { myObject = x, hashSet = new HashSet(x.id) })
.GroupBy(x => x.hashSet, HashSet<int>.CreateSetComparer())
.SelectMany(x => x.GroupBy(y => y.myObject.dept))
If you want to perform only one GroupBy you could store the HashSet in a Tuple or custom class, but then you would have to create your own IEqualityComparer.
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;
});
In my program, I have a class like this:
Class Customer{
double Start;
double Finish;
double Wait;
}
and I created an array of this class:
Customer[] customer = new Customer[300];
How I can sort this array according to Start values Descending or Ascending?
Thanks...
You could use the Array.Sort method to sort the array in-place:
Array.Sort(customer, (x, y) => x.Start.CompareTo(y.Start));
or in descending order
Array.Sort(customer, (x, y) => y.Start.CompareTo(x.Start));
If would prefer to use a List of Customer, however you can apply the same function on the array:
List<Customer> customerList = new List<Customer>;
var orderedCustomerList = customerList.OrderBy(item => item.Start);
Refer to:
Enumerable.OrderBy Method
Enumerable.OrderByDescending Method
In ascending order by Start:
var sortedCustomers = customer.OrderBy(c => c.Start);
And descending order by Start:
var sortedCustomers = customer.OrderByDescending(c => c.Start);
you need to use icomparer and you need to write your custom code after implementing icomparer in your class
you need to implement IComparable for your Customer class.
http://msdn.microsoft.com/en-us/library/system.icomparable%28v=vs.80%29.aspx
C# Tutorial - Sorting Algorithms
Sorting algorithm
You can also use LINQ Dynamic Sort With LINQ
How to sort an array of object by a specific field in C#?
I have a list that I want to sort using to parameters. That means it are all values and if for example I have
A 2/2
B 3/3
C 3/4
I want the sorting C B A
I tried to implement that the following way:
methods.Sort((y, x) => x.GetChangingMethodsCount().CompareTo(y.GetChangingMethodsCount()));
methods.Sort((y, x) => x.GetChangingClassesCount().CompareTo(y.GetChangingClassesCount()));
First sort the list with the second parameter and then sort it again with the first parameter. But the ordering isn0t correct. Any hints how to achieve that?
What you need to do is combine the two sort keys into a single function. If the first comparison returns 0, only then try the second one:
methods.Sort((y, x) =>
{
int sort = x.GetChangingClassesCount().CompareTo(y.GetChangingClassesCount());
if (sort == 0)
sort = x.GetChangingMethodsCount().CompareTo(y.GetChangingMethodsCount());
return sort;
});
Probably the easiest way is to use the OrderBy and ThenBy extension methods like that :
methods.OrderByDescending(x => x.GetChangingMethodCount()).
ThenByDescending(x => x.GetChangingClassesCount()).
ToList();
It's not clear (to me at least) if this is what you want based on your example, but you could give this a try:
var sortedMethods = methods.OrderByDescending(m => m.GetChangingMethodsCount()).ThenByDescending(m => m.GetChangingClassesCount());
I have an ObservableCollection<myClass> list. It contains a 10 objects of type MyClass.
class MyClass
{
string name;
int age;
}
If I want to find all items in list where age = 10, can I use the Contains method?
If yes how can I do this without using iteration?
var age10 = list.Where(i => i.age == 10);
Lots more queries here: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
No, Contains only looks for a specific value, not something matching a predicate. It also only finds one value rather than every matching value.
You can, however, use Where from LINQ to Objects, assuming you're on .NET 3.5 or higher:
foreach (var item in list.Where(x => x.Age == 10))
{
// Do something with item
}
Since ObservableCollection<T> implements Collection<T> which implements IEnumerable<T>...you can use the LINQ to Object extension methods to make this simple (even though it will use iteration in the background):
var results = list.Where(m => m.age == 10);
As others have stated, using .Where(i => i.Age == 10) would be the correct way to get the result stated in the question. You would use .Contains() to check your collection for a specific instance of your class.
You can use linq to do this but not Contains
var foo = from bar in myCollection where bar.age == 10 select bar;