Lambda How to reordering elements in list ascending order and place null value at the back?

StackOverflow https://stackoverflow.com/questions/22142976

  •  19-10-2022
  •  | 
  •  

Question

Says I have ListA={null,3,2,null}.

ListA.OrderBy(x=>x.ID) //would return me null,null,2,3

If my objective is to get 2,3,null,null, currently I can only think of extracting out the null item, and manually pump into the back.

Is there a clean approach where it will return me 2,3,null,null?

Was it helpful?

Solution

You can use OrderByDescending + ThenBy(assuming that it's aList<int?>):

var orderedList = ListA
     .OrderByDescending(x => x.HasValue)
     .ThenBy(x => x);

x.HasValue returns true or false where true is higher than false. That's why i'm using OrderByDescending.

If you want to sort the original list i would use List.Sort with a custom Compaison<T> that treats null as highest value:

ListA.Sort((a1, a2) => (a1 ?? int.MaxValue).CompareTo(a2 ?? int.MaxValue));

This is more efficient since it doesn't need to create a new list.

OTHER TIPS

As an alternative to Tim's answer you could write your own IComparer<T> which does the custom sorting algorithm for you.

var array = list.OrderBy(x => x, new NullableIntComparer())
            .ToArray();

class NullableIntComparer : IComparer<int?>
{
    public int Compare(int? x, int? y)
    {
        if (x.HasValue && y.HasValue)
        {
            return x.Value.CompareTo(y.Value);
        }
        if (x.HasValue)
        {
            return -1;
        }
        if (y.HasValue)
        {
            return 1;
        }
        return 0;
    }
}

Tried the following:

class Program
    {
        class A
        {
            public A(){}
            public int? ID { get; set; }
        }
        static void Main(string[] args)
        {
            var listA = new List<A>
                {
                    new A(){ID = null},
                    new A(){ID = 2},
                    new A(){ID = null},
                    new A(){ID = 3},

                };

            var result = listA.OrderByDescending(x => x.ID != null).ThenBy(x => x.ID);

            foreach (var a in result)
            {
                Console.WriteLine(a.ID);
            }

        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top