使用Linq的列表顺序与sort不同

时间:2010-09-01 04:46:36

标签: c# linq list sorting

我想证实这一点,我试图使用Linq对我的班级列表进行排序。但是当我使用排序函数时,数据的顺序似乎没有以相同的方式排序。

假设该列表包含4个ComputeItem 并且它们的所有A都设置为1,所有的B,C,D都设置为零。

案例1:

ItemList =
    ItemList
        .OrderByDescending(m => m.A)
        .ThenBy(m => m.B)
        .ThenBy(m => m.C)
        .ThenBy(m => m.D)
        .ToList<ComputeItem>();

案例2:

ItemList.Sort(
    delegate(ComputeItem item1, ComputeItem item2)
    {
        if (item1.A == item2.A)
        {
            if (item1.B == item2.B)
            {
                if (item1.C == item2.C)
                {
                    return item1.D - item2.D;
                }
                else
                {
                    return item1.C - item2.C;
                }
            }
            else
            {
                return item1.B - item2.B;
            }
        }
        else
        {
            return item2.A - item1.A;
        }
    }
);

第一种结果是它没有移动任何东西。
第二种排序的结果是将其排序为不同的顺序 原始秩序[1,2,3,4]
案例1新订单[1,2,3,4]
案例2新订单[3,4,1,2]

现在问题发生在我使用CASE2并尝试将其迁移到CASE 1之前。但是行为不能比之前大幅改变。知道为什么CASE 2移动了订单吗?

3 个答案:

答案 0 :(得分:10)

OrderByOrderByDescendingThenByThenByDescending使用的排序算法是stable QuickSort。来自MSDN documentation

  

此方法执行稳定排序;   也就是说,如果两个元素的键   是相等的,元素的顺序   保留下来。

List<T>.Sort使用QuickSort的不稳定版本,它不一定保留相等元素的原始顺序。同样,来自MSDN documentation

  

此方法使用Array.Sort,其中   使用QuickSort算法。这个   实现执行不稳定   分类;也就是说,如果有两个元素   平等,他们的订单可能不是   保留。

这解释了您所看到的差异。显然,两者的最终结果是项目按照比较机制的方式排序。这只是相等元素出现的顺序,List<T>.Sort未指定。

好消息是,您将不稳定排序转移到 稳定排序。我很难想象这对你来说可能是一个重大改变(什么样的软件需要那种不稳定?)。如果有的话,它应该使你的程序更加可预测。

答案 1 :(得分:3)

我认为Rahul的头部钉在了头上。 就个人而言,我会发现以下内容对您的案例2更具可读性:

int result;

// Sort by A descending => invert the sign of the result
result = - item1.A.CompareTo(item2.A);
if (result != 0) return result;

// then by B ascending
result = item1.B.CompareTo(item2.B);
if (result != 0) return result;

// then by C ascending
result = item1.C.CompareTo(item2.C);
if (result != 0) return result;

// then by D ascending
result = item1.D.CompareTo(item2.D);
if (result != 0) return result;

// ... add other comparisons here if you ever need to in the future

return result;

答案 2 :(得分:2)

这是对的吗?

return item2.A - item1.A;

或应该是

return item1.A - item2.A;