c#中的列表排序问题

时间:2011-04-04 15:06:01

标签: c# sorting

public static List<PreviewSchedule> BuildPreviewSchedule(Chatham.Business.Objects.Transaction transaction)
        {
            List<PreviewSchedule> items = new List<PreviewSchedule>();
            List<ScheduleItem> scheduleItems = new List<ScheduleItem>(transaction.ScheduleCollection.FindAll(row => row.IsDeleted == false));

            bool allFromDateFilledIn = !scheduleItems.Exists(item => !item.FromDate.HasValue);
            bool allFloatingFromDateFilledIn = !scheduleItems.Exists(item => !item.FloatingFromDate.HasValue);

            scheduleItems.Sort((a, b) => a.FromDate.GetValueOrDefault().CompareTo(b.FromDate.GetValueOrDefault()));

            scheduleItems.Sort((a, b) => SortIt(a, b, allFromDateFilledIn, allFloatingFromDateFilledIn));

            for (int i = 0; i < scheduleItems.Count; i++)
            {
                items.Add(new PreviewSchedule
                {
                    Drop = i == 0 ? "$0.00" :
                    ((scheduleItems[i - 1].PrincipalNotionalAmount - scheduleItems[i].PrincipalNotionalAmount)).Value.ToString(Format.CurrencyCentsIncludedFormatStringDollarSign),
                    EndDate = GetDateOrNull(scheduleItems[i].ToDate),
                    StartDate = GetDateOrNull(scheduleItems[i].FromDate),
                    Notional = scheduleItems[i].PrincipalNotionalAmount.Value.ToString(Format.CurrencyCentsIncludedFormatStringDollarSign),
                    FloatingEndDate = GetDateOrNull(scheduleItems[i].FloatingToDate),
                    FloatingStartDate = GetDateOrNull(scheduleItems[i].FloatingFromDate)
                });
            }
            return items;
        }

以下是我们调用的方法,将我们的日程安排返回到mvc应用程序的前端。现在,这个列表每次都以相同的方式混合特定模型的最后两行。看看图片: enter image description here

表的最后两行,你可以明显地看到最后两行被切换,因为日期不会相互跟随。这种方法正在吐出那些混淆的日期,我认为这是排序的问题。你们中的任何人都可以看到排序会导致这种情况吗?

提前致谢。

编辑:

SortIt()代码:

private static int SortIt(
           Chatham.Business.Objects.ScheduleItem a,
           Chatham.Business.Objects.ScheduleItem b,
            bool allFromDateFilledIn,
           bool allFloatingFromDateFilledIn)
        {
            return SortIt(a.FromDate, a.FloatingFromDate, b.FromDate, b.FloatingFromDate, allFromDateFilledIn, allFloatingFromDateFilledIn);
        }

        private static int SortIt(DateTime? aFrom, 
            DateTime? aFloatingFrom, 
            DateTime? bFrom, 
            DateTime? bFloatingFrom, 
            bool allFromDateFilledIn,
            bool allFloatingFromDateFilledIn)
        {
            DateTime? a = null;
            DateTime? b = null;
            if (allFromDateFilledIn == false && allFloatingFromDateFilledIn == false)
            {
                a = aFrom ?? aFloatingFrom;
                b = bFrom ?? bFloatingFrom;
            }
            else
            {
                a = allFromDateFilledIn ? aFrom : aFloatingFrom;
                b = allFromDateFilledIn ? bFrom : bFloatingFrom;
            }

            if (a.HasValue && b.HasValue)
                return a.Value.CompareTo(b.Value);

            return 0;
        }

2 个答案:

答案 0 :(得分:2)

我注意到倒数第二行是唯一一个填写了所有四个日期的行。我还注意到2013年10月1日是在2013年11月1日之前。我强烈怀疑这些日期是一起比较的。但是,如果不知道SortIt方法的样子,我无法完全诊断或纠正问题。无论如何,这可能是你问题的根源,所以我会把你的努力集中在那里。

考虑填写所有四个日期后会发生什么,并弄清楚如何处理这种情况。

编辑:

现在您已添加了SortIt代码,请查看您的allFromDateFilledInallFloatingFromDateFilledIn标记。对于您的示例数据,这两个都总是错误的,因为From和FloatingFrom列在某处包含至少一个空单元格。因此,您的SortIt方法总是会对此进行评估:

a = aFrom ?? aFloatingFrom;
b = bFrom ?? bFloatingFrom;

...这意味着将来自不同列的值进行比较。这也意味着当From和FloatingFrom都存在时,From总是作为比较值获胜。

编辑2:

您可以尝试使用内置if/else替换上面的内容:

if (aFrom != null && bFrom != null)
{
    a = aFrom;
    b = bFrom;
}
else if (aFloatingFrom != null && bFloatingFrom != null)
{
    a = aFloatingFrom;
    b = bFloatingFrom;
}
else
{
    a = aFrom ?? aFloatingFrom;
    b = bFrom ?? bFloatingFrom;
}

我觉得这种逻辑可能会被减少/美化,但这种方式似乎最容易理解。请注意,From仍然具有比FloatingFrom更高的优先级。

您可能还想考虑布尔标志正在做什么。它们只会在一个或另一个列完全填满时才会发挥作用,在这种情况下,它们会锁定该列作为比较列。这可能是你想要的,也可能是不必要的。您已经确定From优先于FloatingFrom,因此没有理由覆盖该规则,我只是为了保持一致性而遵循它。只是一个想法。

答案 1 :(得分:1)

这里有一个问题:

if (a.HasValue && b.HasValue)
  return a.Value.CompareTo(b.Value);

return 0;

如果ab没有值,则可能会返回不一致的返回值。想象一下,如果sort方法使用a=2011/04/24b=null来调用它。它将返回0.后来在同一种类型中,可能会使用a=nullb=2011/03/24调用它。在这两种情况下,该方法都将返回0.

当比较方法返回不一致的值时,List.Sort的行为是未定义的。在这里你有一个案例,给定三个值(我将使用数字,但相同的日期将成立),你不能给出可靠的排序。

a = 5
b = 10
c = null

比较ac会返回0.比较bc也会返回0。一个假定如果a==cb==c,则a==b。但在这种情况下a < b。这将导致Sort无法预测。在这种情况下,某些排序方法会进入无限循环,或者崩溃。