简体   繁体   中英

C# custom sorting. All Ns followed by ASC order

I am working on WPF application using Infragistics XamDataGrid. I have few columns that I need to sort to work like below.

I will have values like -1.00,N,1.73, N, -5.6, N, 7.. I need sort to be like below

Asc order

N
N
-5.6
-1.00
1.73
7

Desc order

7
1.73
-1.00
-5.6
N
N

I just need custom sort like below. Unable to get what I need to put.

public class MyCustomSort : IComparer
{
    public int Compare(object x, object y)
    {
        if (x == null || y == null) return 1;

        string x1, y1;            
        x1 = x.ToString();
        y1 = y.ToString();

        if (x1 == "N" || y1 == "N") return 1;

        return x1.CompareTo(y1);
    }
}

UPDATE: Thanks to user2023861 . I will accept his answer after I finish my thorough testing. I changed my Compare code below. I am still testing and initial testing looks good. Please let me know your views on this.

public int Compare(object x, object y)
        {
            //put nulls first
            if (x == null) return 1;
            if (y == null) return -1;
            //put Ns second after nulls
            if (x.ToString() == "N") return -1;
            if (y.ToString() == "N") return 1;
            double doubleX;
            double doubleY;
            bool xParsed = Double.TryParse(x.ToString(), out doubleX);
            bool yParsed = Double.TryParse(y.ToString(), out doubleY);
            if(xParsed && yParsed)
            {
                // both X and Y are doubles
                return doubleX.CompareTo(doubleY);
            }

            return 1;
        }

I marked user2023861 post below as answer since it took me into right direction. I changed my code as per above and testing so far looks good. I will update this if I encounter any issues.

Thanks all.

Read about the return values of the Compare method here https://msdn.microsoft.com/en-us/library/system.collections.icomparer.compare(v=vs.110).aspx In summary, result < 0 means x is first, result == 0 means x == y, and result > 0 means y comes first.

For instance, this line:

if (x == null || y == null) return 1;

returns a result stating that x should come after y because the result is greater than zero.

What your algorithm is doing now is this:

if x or y is null, y comes first
if x or y is "N", y comes first
otherwise compare x as a string to y as a string and return that

Edit: here's your answer (make sure to test this plenty, I haven't tried it)

public class MyCustomSort : IComparer
{
    public int Compare(object x, object y)
    {
        //put nulls first
        if (x == null) return 1;
        if (y == null) return -1;

        string x1, y1;            
        x1 = x.ToString();
        y1 = y.ToString();

        //put Ns second after nulls
        if (x1 == "N") return -1;
        if (y1 == "N") return 1;

        return x.CompareTo(y); //assuming these are doubles
    }
}

I tried below in quick console application and looks it works :

List<object> lst = new List<object> { "N", "N", -5.6, -1.00, 1.73, 7 };
            var result=
            lst.OrderByDescending(item =>
            {
                double val = 0;
                if (double.TryParse(item.ToString(), out val))
                {
                    return val;
                }
                return double.MaxValue; /*dummy number*/
            }).ToList();

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

Below is screen shot when snippet executed by OrderBy and OrderbyDescending operator :

在此处输入图片说明

You input are maid from strings, doubles and ints. You can group values by type and then apply sorting. Try this code:

var input = new object[] {-1.00, "N", 1.73, "N", -5.6, "N", 7};

// get all strings
var allN = input.Where(n => n is string);

// now filter numerics
var ints = input.Where(x => x is double).Cast<double>();
var doubles = input.Where(x => x is int).Select(x => (double) (int) x);

After splitting input by types you can recombine it with this code:

var asc = allN.Concat(ints.Concat(doubles)
  .OrderBy(x => x).Cast<object>()).ToArray();
var desc = ints.Concat(doubles)
  .OrderByDescending(x => x).Cast<object>().Concat(allN).ToArray();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM