-2

I want to create a similar number-text comparer to the one described in How to create custom common number-text comparer in C# to sort numeric/string list?.

public class NumberTextComparer : IComparer<string>
    {
        public int Compare(string s1, string s2)
        {
            double number1, number2;
            var isS1Numeric = double.TryParse(s1, out number1);
            var isS2Numeric = double.TryParse(s2, out number2);

            if (isS1Numeric && isS2Numeric)
            {
                if (number1 > number2) return 1;
                if (number1 < number2) return -1;
                return 0;
            }
            if (isS1Numeric)
                return 1;
            if (isS2Numeric)
                return -1;

            bool s1StartsWithLetter = char.IsLetter(s1.FirstOrDefault());
            bool s2StartsWithLetter = char.IsLetter(s2.FirstOrDefault());

            if (s1StartsWithLetter == s2StartsWithLetter)
                return String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
            if (s1StartsWithLetter)
                return -1;
            return 1;
        }
    }

var numericList = new List<string>{"100", "--", "-0.98", "N/A", "0.00", "-888"};
var stringList = new List<string> {"Smith", "--", "Peter", "", "Jim", "Ken", "NA"};

Console.WriteLine(String.Join(", ", numericList.OrderBy(v => v, new NumberTextComparer())));
Console.WriteLine(String.Join(", ", stringList.OrderBy(v => v, new NumberTextComparer())));

Which gives following output:

  1. N/A, --, -888, -0.98, 0.00, 100
  2. Jim, Ken, NA, Peter, Smith, , --

But I want in the string sorting: "" or -- should come first instead of last in ascending order. Numeric sort is as excepted.

So the expected result will be:

  1. Numeric Sort Asc -> N/A, --,-888, -0.98, 0.00, 100
  2. String Sort Asc -> , --, Jim, Ken, NA, Peter, Smith

Is it possible to achieve this?

Community
  • 1
  • 1
  • What have you tried? Please provide a good [mcve] with a precise explanation of what that code does and how that's different from what you want. – Peter Duniho Jan 14 '16 at 04:29
  • Updated with code snippet. Thanks! – Sanvi Deshpande Jan 14 '16 at 16:37
  • Thanks for the code. Unfortunately, I'm still not really understanding the question. Two issues: **1)** your "expected result" examples don't seem consistent with each other. In the first, the string `"--"` comes after `"N/A"`, but in the second it comes before `"NA"` (and all other non-numeric). From your description, I'd think you'd want it before `"N/A"` also. Why not? – Peter Duniho Jan 14 '16 at 17:39
  • **2)** I don't see anything in your code example that attempts to sort `"--"` and `""` before other strings; i.e. I can't see _what you've tried_. I would expect you can use the same technique you're currently using for numerics, i.e. check the input for the specific pattern you want to handle exceptionally, and then treat them in the appropriate way; what specifically are you having trouble with? – Peter Duniho Jan 14 '16 at 17:39

1 Answers1

0

As per my understanding you require 2 different sort behavior in case of Number and String data. So you can achieve this by passing required type as below-

 public enum SortColumnType
 {
        Numeric=1,
        String=2
 }

public class NumberTextComparer : IComparer<string>
    {
        public SortColumnType ColumnType { get; set; }

        public NumberTextComparer(SortColumnType columnType)
        {
            ColumnType = columnType;
        }

        private int CustomNumberSort(string s1, string s2)
        {
            double number1, number2;
            var isS1Numeric = double.TryParse(s1, out number1);
            var isS2Numeric = double.TryParse(s2, out number2);

            if (isS1Numeric && isS2Numeric)
            {
                if (number1 > number2) return 1;
                if (number1 < number2) return -1;
                return 0;
            }
            if (isS1Numeric)
                return 1;
            if (isS2Numeric)
                return -1;

            var s1StartsWithLetter = !string.IsNullOrEmpty(s1) && char.IsLetterOrDigit(s1[0]);
            var s2StartsWithLetter = !string.IsNullOrEmpty(s2) && char.IsLetterOrDigit(s2[0]);

            if (s1StartsWithLetter == s2StartsWithLetter)
                return String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
            if (s1StartsWithLetter)
                return -1;
            return 1;
        }

        public int Compare(string s1, string s2)
        {
            return ColumnType.Equals(SortColumnType.Numeric)
                ? CustomNumberSort(s1, s2)
                : String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
        }
    }

stringList.OrderBy(str => str, new NumberTextComparer(SortColumnType.String));
numericList.OrderBy(str => str, new NumberTextComparer(SortColumnType.Numeric));
Sumit Deshpande
  • 2,155
  • 2
  • 20
  • 36