Sort a Custom Class List<T>

Sort a Custom Class ListT

One way to do this is with a delegate

List<cTag> week = new List<cTag>();
// add some stuff to the list
// now sort
week.Sort(delegate(cTag c1, cTag c2) { return c1.date.CompareTo(c2.date); });

C# sort custom class list

The easiest way is probably to implement the IComparable<T> interface. Implementing this interface on your MyItem class will ensure that when ordering a list of MyItem instances, the ordering as specified in the CompareTo method will be used. For your use case, this would result in code like this:

public class MyItem : IComparable<MyItem>
{
public string OrderItem { get; set; }
public string Status { get; set; }

public int CompareTo(MyItem other)
{
if (other == null)
{
return 1;
}

if (other.Status == this.Status)
{
return 0;
}

var statusAsInt = this.Status == "Error" ? 0 : (this.Status == "Pending" ? 1 : 2);
var otherStatusAsInt = other.Status == "Error" ? 0 : (other.Status == "Pending" ? 1 : 2);

if (statusAsInt == otherStatusAsInt)
{
return 0;
}

return statusAsInt < otherStatusAsInt ? -1 : 1;
}
}

internal class Program
{
private static void Main(string[] args)
{
var myItems = new List<MyItem> { new MyItem { Status = "Pending" }, new MyItem { Status = "Error" }, new MyItem { Status = "Success " } };

myItems.Sort();

foreach (var myItem in myItems)
{
Console.WriteLine(myItem.Status);
}
}
}

How to sort a list of a custom class by a variable in that custom class? c#

Sort a list by calling OrderBy. Note this return an IEnumerable<T> to you will have to call ToList() to get a list again:

var list = new List<Foo>();
var sortedList = list.OrderBy(foo => foo.bar).ToList();

How to Sort Generic.List(of T) with a custom Class?

I probably shouldn't do this but I will anyway. Here's a solution using IComparable(Of T):

Public Class ListControlItem
Implements IComparable, IComparable(Of ListControlItem)

Public Property Value As String
Public Property Text As String

Public Sub New(value As String, text As String)
Me.Value = value
Me.Text = text
End Sub

Public Overrides Function ToString() As String
Return Text
End Function

Public Function CompareTo(obj As Object) As Integer Implements IComparable.CompareTo
Return CompareTo(DirectCast(obj, ListControlItem))
End Function

Public Function CompareTo(other As ListControlItem) As Integer Implements IComparable(Of ListControlItem).CompareTo
Return Text.CompareTo(other.Text)
End Function

End Class

and then simply sort like this:

myListControlItemList.Sort()

Here's a solution using IComparer(Of T):

Public Class ListControlItem

Public Property Value As String
Public Property Text As String

Public Sub New(value As String, text As String)
Me.Value = value
Me.Text = text
End Sub

Public Overrides Function ToString() As String
Return Text
End Function

End Class

Public Class ListControlItemComparer
Implements IComparer, IComparer(Of ListControlItem)

Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Return Compare(DirectCast(x, ListControlItem), DirectCast(y, ListControlItem))
End Function

Public Function Compare(x As ListControlItem, y As ListControlItem) As Integer Implements IComparer(Of ListControlItem).Compare
Return x.Text.CompareTo(y.Text)
End Function

End Class

and then sort like this:

myListControlItemList.Sort(New ListControlItemComparer)

Here's a solution using the Comparison(Of T) delegate, which does an ad hoc sort without any other classes or interfaces:

myListControlItemList.Sort(Function(x, y) x.Text.CompareTo(y.Text))

Notice that, in all three cases, the actual comparison is pretty much exactly the same.

By the way, also note that it is considered good practice to implement both the non-generic and generic versions of an interface when both exist. AS I have demonstrated here, the non-generic implementation can simply perform a cast and pass the work off to the generic implementation.

As I think I mention in my blog posts, the IComparable interface is a good option when there is an obvious way that items should be compared in all or most cases. Once the type being compared implements its own comparison, no one has to do any extra work to use it. The IComparer interface is a good option if there are multiple ways the items could be compared and/or the comparison is complex and comparisons will be required in multiple places. It allows you to put all the comparison logic in one place and then use it in multiple places with little extra code. The Comparison delegate is good for ad hoc sorting because you put the logic right where you need to use it.

As an aside, I have used properties in these examples and you should do the same. Properties should almost always be used for exposing data publicly and they are also required for use in data-binding. In this case, it might even be appropriate to use ReadOnly properties, if the intention is that the data not be changed once the objects are created.

As a bonus, here's an example of a complex comparison. I'll do it by extending the third example above for simplicity but it can be done in any of the three cases because, as I said, the actual comparison is done in pretty much exactly the same way in all three cases.

myListControlItemList.Sort(Function(x, y)
'Sort by Text by default.
Dim result = x.Text.CompareTo(y.Text)

If result = 0 Then
'Sort by Value if Text is equal.
result = x.Value.CompareTo(y.Value)
End If

Return result
End Function)

How do I sort an array of custom classes?

If you implement IComparable<Donator> You can do it like this:

public class Donator :IComparable<Donator>
{
public string name { get; set; }
public string comment { get; set; }
public double amount { get; set; }

public int CompareTo(Donator other)
{
return amount.CompareTo(other.amount);
}
}

You can then call sort on whatever you want, say:

var donors = new List<Donator>();
//add donors
donors.Sort();

The .Sort() calls the CompareTo() method you implemented for sorting.

There's also the lambda alternative without IComparable<T>:

var donors = new List<Donator>();
//add donors
donors.Sort((a, b) => a.amount.CompareTo(b.amount));

Sort a list by a custom order

Assuming linkTypes (the private string array) is in the same class as links (the list of LinkElement), you can use LINQ's OrderBy with a simple lambda expression:

var sortedLinks = links.OrderBy(le => Array.IndexOf(linkTypes, le.linkType)).ToList()

sort list of Controls from a custom class type

You have too many left parentheses. I would use OfType or Cast or store the controls in a List<Dashboard_Env_Details> instead:

List<Control> Sortedlc = lc.Cast<Dashboard_Env_Details>()
.OrderBy(o => o.custTask.getNoInvalidObjects)
.Select(o => (Control) o)
.ToList();

If the list contains also other controls you could use OfType.

How to Sort a ListT by a property in the object

The easiest way I can think of is to use Linq:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();

How to sort a List of generic objects

Comparable

I tried with Comparable interface but it doesn't work

If there's only one way to compare teams that make sense from the perspective of your application - by their ranking, then Team objects have a natural ordering and hence class Team should implement Comparable.

A quote from the documentation:

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.

That's how it might be done:

public static class Team<T extends Player> implements Comparable<Team<T>> {
public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
Comparator.comparingInt(Team::ranking);

// fields, getters, etc.

public int ranking() {
return (win * 2) + draw;
}

@Override
public int compareTo(Team<T> other) {
return BY_TEAM_RANKING.compare(this, other);
}
}

For the sake of conciseness, method compareTo in the code shown above internally uses Comparator defined as a static field (similar approach you can find in the book "Effective Java" by Joshua Bloch, have a look at it for more information on implementing Comparable interface).

To sort the list of teams, use method sort() directly on the list (which is a more fluent alternative of Collection.sort() introduced with Java 8).

public class League<T extends Player> {

private String name;
private List<Team<T>> teams = new ArrayList<>();

public void ranking() {
teams.sort(null); // teams are comparable, hence no need to provide a comparator and null is passed as an argument
}
}

Comparators

In case if there are multiple ways how teams need to be sorted in different scenarios, then Team class should not implement Comparable, don't go with way.

You can define comparators for different use-cases as public static fields in the Team class, like below:

public static class Team<T extends Player> {

public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
Comparator.comparingInt(Team::ranking);

public static final Comparator<Team<? extends Player>> BY_TEAM_NAME =
Comparator.comparing(Team::getName);

// the rest code
}

And then apply them depending on a particular case:

public void ranking() {
teams.sort(Team.BY_TEAM_RANKING);
}

Sidenote: write your code against interfaces, not implementations like ArrayList. See What does it mean to "program to an interface"?



Related Topics



Leave a reply



Submit