Home > Software engineering >  Sorting the list by two parameters simultaneously C#
Sorting the list by two parameters simultaneously C#

Time:05-08

I would like to sort lists with structures by certain fields/properties of structures. For example there is a structure:

public struct Some
{
    public int index;
    public DateTime date;
}

Do I have an opportunity to sort such a structure by two parameters simultaneously using the existing methods? Say, at the top of the list of such structures place those that will have the latest date and the largest index. Is it possible to sort simultaneously taking into account these two parameters?

CodePudding user response:

Yes you can using LINQ

with the OrderBy method

OrderBy and ThenBy are the mothods you need.

Example:

list.OrderBy(x => x.index).ThenBy(x => x.date)

If you add Descending you can also sort it the other way round.

CodePudding user response:

Use custom sort comparison function.

Example 1:

    public struct MyItem
    {
        public int index;
        public DateTime date;
    }
    class Program
    {
        static void Main(string[] args)
        {
            var items = new MyItem[]{
                new MyItem{index=9, date=DateTime.Now},
                new MyItem{index=4, date=DateTime.Now},
                new MyItem{index=3, date=DateTime.Now},
                new MyItem{index=5, date=DateTime.Now},
                new MyItem{index=5, date=DateTime.Now   TimeSpan.FromDays(1)},
                new MyItem{index=6, date=DateTime.Now},
            };
            // sort by index, if equal then sort by date
            Array.Sort(items, (x, y) =>
            {
                if (x.index == y.index)
                    return x.date.CompareTo(y.date);
                return x.index.CompareTo(y.index);
            });

            foreach (var item in items)
                Console.WriteLine($"{item.index} {item.date}");
        }
    }

Example 2:

var items = new List<MyItem>{
    new MyItem{index=9, date=DateTime.Now},
    new MyItem{index=4, date=DateTime.Now},
    new MyItem{index=3, date=DateTime.Now},
    new MyItem{index=5, date=DateTime.Now},
    new MyItem{index=5, date=DateTime.Now   TimeSpan.FromDays(1)},
    new MyItem{index=6, date=DateTime.Now},
};
// sort by index, if equal then sort by date
items.Sort((x, y) => x.index.CompareTo(y.index) == 0 ? x.date.CompareTo(y.date) : x.index.CompareTo(y.index));

Example3: Linq

            var items = new List<MyItem>{
                new MyItem{index=9, date=DateTime.Now},
                new MyItem{index=4, date=DateTime.Now},
                new MyItem{index=3, date=DateTime.Now},
                new MyItem{index=5, date=DateTime.Now},
                new MyItem{index=5, date=DateTime.Now   TimeSpan.FromDays(1)},
                new MyItem{index=6, date=DateTime.Now},
            };
            // sort by index, if equal then sort by date
            var newItems = items.OrderBy(x => x.index).ThenBy(x => x.date);

CodePudding user response:

If you want to Sort in place and you don't want to implement IComparable<Some> or IComparer<Some>:

List<Some> myList = ...

...

myList.Sort((left, right) => {
  // latest dates on the top (note - for descending sorting)
  int result = -left.date.CompareTo(right.date);

  // on tie when left and right have the same date we compare indexes
  return result == 0 
    ? -left.index.CompareTo(right.index)
    :  result; 
});

In case you have several fragments where you want to sort list in such a way, you can implement a comparer:

public sealed class SomeComparer : IComparer<Some> { 
  public int Compare(Some left, Some right) {
    // latest dates on the top (note - for descending sorting)
    int result = -left.date.CompareTo(right.date);

    // on tie when left and right have the same date we compare indexes
    return result == 0 
      ? -left.index.CompareTo(right.index)
      :  result;
  }
} 

Then whenever you want to sort the list:

myList.Sort(new SomeComparer());

Finally, if it's the only order you want to sort Some items, you can make Sort comparable:

public struct Some : IComparable<Some>
{
    public int index;
    public DateTime date;

    //TODO: implement Equals and GetHashCode 

    public bool CompareTo(Some other) {
      int result = -date.CompareTo(other.date);

      return result == 0 
        ? -index.CompareTo(other.index)
        : result;
    }
}

and you can put

myList.Sort();

CodePudding user response:

You can use LINQ to easily sort items in a list by the values contained in a that list.

using System.Linq;

...

myStructs.OrderBy(s => s.index).ThenBy(s => s.date)

Will put everything in order by index. Items with equal index would be sorted by date.

  • Related