【问题标题】:C# Array.Sort inconsistent resultsC# Array.Sort 不一致的结果
【发布时间】:2014-03-21 13:48:33
【问题描述】:

我正在尝试对一个制表符分隔的字符串数组进行排序。我在每个元素的制表符上调用 split 函数以将字符串分解为字符串数组。然后我对日期元素进行比较以返回它们应该在的顺序。如果日期相等,我对字符串字段进行二次比较。我的 IComparer 接口实现如下所示:

class CompareLines : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string[] bSplitX = x.Split('\t');
        string[] bSplitY = y.Split('\t');

        int bYearX = Int32.Parse(bSplitX[4].Substring(4, 4));
        int bMonthX = Int32.Parse(bSplitX[4].Substring(0, 2));
        int bDayX = Int32.Parse(bSplitX[4].Substring(2, 2));

        int bYearY = Int32.Parse(bSplitY[4].Substring(4, 4));
        int bMonthY = Int32.Parse(bSplitY[4].Substring(0, 2));
        int bDayY = Int32.Parse(bSplitY[4].Substring(2, 2));

        DateTime bTempDateX = new DateTime(bYearX, bMonthX, bDayX);
        DateTime bTempDateY = new DateTime(bYearY, bMonthY, bDayY);

        if (DateTime.Compare(bTempDateX, bTempDateY) > 0)
        {
            return 1;
        }
        else if (DateTime.Compare(bTempDateX, bTempDateY) < 0)
        {
            return -1;
        }
        else if (DateTime.Compare(bTempDateX, bTempDateY) == 0)
        {
            if (String.Compare(bSplitX[3], bSplitY[3]) > 0)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
        else
        {
            Console.WriteLine("ahhh wtf"); //should never be reached. This message has never appeared in my console.
            return 0;
        }
    }
}

我的问题是它有时会起作用,而其他时候不起作用。有没有人有任何理由说明上述代码不能 100% 工作?

这几天一直在伤害我的大脑,我真的不明白为什么它不起作用。

【问题讨论】:

  • 如果不起作用会怎样?
  • 你为什么要自己解析日期,而不是使用DateTime.ParseExact?在没有任何有关输入、预期输出或出错时会发生什么信息的情况下,您希望我们如何为您提供帮助?
  • 我不知道 ParseExact。输入是一个字符串数组。相关字段是一个字符串(位置 4 的元素),表示 MMddyyyy 格式的日期和一个任意字符串,以比较日期是否相等(位置 3 的元素。示例可能是“f”“e”“c”等. 它们可以有多个字符,这就是它们是字符串的原因)预期的输出是按日期升序排序的数组,如果日期匹配,则其次是按字符串排序。我不确定到底出了什么问题。日期是为了某个点然后未定义(可能是 2008 年到 2010 年到 2009 年)
  • 您知道这些日期在数学上是最适合比较的格式吗?一秒钟,我会证明我的意思......
  • @Dave yyyyMMdd 将是比较的最佳选择,实际上是我之前正在做的,但它仍然无法正常工作。我可能会将其改回 int 比较,而不是创建 DateTime 对象以提高性能。

标签: c# arrays sorting


【解决方案1】:

我看到的唯一漏洞是如果日期 字符串相同,那么您不会返回 0:

        if (String.Compare(bSplitX[3], bSplitY[3]) > 0) {
            return 1;
        } else {
            return -1;  // if they are equal it will return -1.
        }

这会打乱排序程序。

这是一个更简洁的版本:

   int dateCompare = DateTime.Compare(bTempDateX, bTempDateY);

   if (dateCompare == 0) 
        return String.Compare(bSplitX[3], bSplitY[3]);
   else
       return dateCompare ;

【讨论】:

    【解决方案2】:

    换一个怎么样

    if (String.Compare(bSplitX[3], bSplitY[3]) > 0) {
      return 1;
    } else {
      return -1;
    }
    

    return String.Compare(bSplitX[3], bSplitY[3]);
    

    如果 X 和 Y 字符串相等,您当前的代码表示 Y 小于 X。 以下是 ParseExact 方法的代码。

    class CompareLines : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            string[] bSplitX = x.Split('\t');
            string[] bSplitY = y.Split('\t');
    
            DateTime bTempDateX = DateTime.ParseExact(bSplitX[4], "MMddyyyy", null);
            DateTime bTempDateY = DateTime.ParseExact(bSplitY[4], "MMddyyyy", null);
    
            if (DateTime.Compare(bTempDateX, bTempDateY) > 0)
                return 1;
            else if (DateTime.Compare(bTempDateX, bTempDateY) < 0)
                return -1;
            else
                return String.Compare(bSplitX[3], bSplitY[3]);
        }
    }
    

    【讨论】:

    • 你应该解释为什么这个改变很重要。
    • 我认为这可能有效。初始通过将它们按正确的顺序排列。让我再做几个测试,如果可行,我会将其标记为答案。
    【解决方案3】:

    首先,您无需重写框架中内置的比较逻辑,只要您正确设置了第一手数据,它就已经返回了您期望的结果。正如乔恩建议的那样,只需解析日期,然后返回日期的比较。我添加了一个属性 IncomingFormat ,考虑到您的输入,它可能没有用。

    编辑:更简洁/清晰:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    
    namespace ConsoleApplication1
    {
        public class CompareLines : IComparer<string>
        {
            public string IncomingFormat { get; set; }
    
            public int Compare(string first, string second)
            {
                var date1 = DateTime.ParseExact(first, IncomingFormat, CultureInfo.InvariantCulture);
                var date2 = DateTime.ParseExact(second, IncomingFormat, CultureInfo.InvariantCulture);
    
                return date1.CompareTo(date2);
            }
        }
    
        internal class Program
        {
            private static void Main()
            {
                const string dataFormat = "MM\tdd\tyyyy";
    
                var comparer = new CompareLines
                {
                    IncomingFormat = dataFormat
                };
    
                int result;
                string date1, date2;
    
                date1 = DateTime.Parse("1/1/2000").ToString(dataFormat);
                date2 = DateTime.Parse("1/1/2000").ToString(dataFormat);
                result = comparer.Compare(date1, date2);
                Debug.Assert(result == 0);
                Console.WriteLine("{0} compare {1} = {2}", date1, date2, result);
    
                date1 = DateTime.Parse("1/1/2000").ToString(dataFormat);
                date2 = DateTime.Parse("1/2/2000").ToString(dataFormat);
                result = comparer.Compare(date1, date2);
                Debug.Assert(result == -1);
                Console.WriteLine("{0} compare {1} = {2}", date1, date2, result);
    
                date1 = DateTime.Parse("1/2/2000").ToString(dataFormat);
                date2 = DateTime.Parse("1/1/2000").ToString(dataFormat);
                result = comparer.Compare(date1, date2);
                Debug.Assert(result == 1);
                Console.WriteLine("{0} compare {1} = {2}", date1, date2, result);
    
                Console.ReadLine();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 2013-04-30
      • 2014-09-21
      • 2021-03-27
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多