【发布时间】:2011-06-30 04:09:54
【问题描述】:
stable sort 是一种保持具有相同值的元素的相对顺序的排序。
ArrayList.Sort 上的文档说,当提供 IComparer 时,排序是稳定的:
如果 comparer 设置为 null,此方法执行比较排序(也称为不稳定排序);也就是说,如果两个元素相等,则可能不会保留它们的顺序。相反,稳定排序保留了相等元素的顺序。要执行稳定排序,您必须实现自定义 IComparer 接口。
除非我遗漏了什么,否则下面的测试用例表明ArrayList.Sort 没有使用稳定的排序:
internal class DisplayOrdered {
public int ID { get; set; }
public int DisplayOrder { get; set; }
public override string ToString() {
return string.Format("ID: {0}, DisplayOrder: {1}", ID, DisplayOrder);
}
}
internal class DisplayOrderedComparer : IComparer {
public int Compare(object x, object y) {
return ((DisplayOrdered)x).DisplayOrder - ((DisplayOrdered)y).DisplayOrder;
}
}
[TestFixture]
public class ArrayListStableSortTest {
[Test]
public void TestWeblinkCallArrayListIsSortedUsingStableSort() {
var call1 = new DisplayOrdered {ID = 1, DisplayOrder = 0};
var call2 = new DisplayOrdered {ID = 2, DisplayOrder = 0};
var call3 = new DisplayOrdered {ID = 3, DisplayOrder = 2};
var list = new ArrayList {call1, call2, call3};
list.Sort(new DisplayOrderedComparer());
// expected order (by ID): 1, 2, 3 (because the DisplayOrder
// is equal for ID's 1 and 2, their ordering should be
// maintained for a stable sort.)
Assert.AreEqual(call1, list[0]); // Actual: ID=2 ** FAILS
Assert.AreEqual(call2, list[1]); // Actual: ID=1
Assert.AreEqual(call3, list[2]); // Actual: ID=3
}
}
我错过了什么吗?如果不是,这是文档错误还是库错误?
显然在 Linq 中使用 OrderBy 可以提供稳定的排序。
【问题讨论】:
-
评论的意图是否可能是“您需要实现自己的 IComparer 以强制排序稳定”而不是“如果您实现自己的 IComparer,排序将是稳定的隐式”?
-
这不是实现比较的好方法。 blogs.msdn.com/b/ericlippert/archive/2011/01/27/…
-
你确定你没有落入这里描述的谬论吗:blogs.msdn.com/b/ericlippert/archive/2011/01/27/… 编辑:呸,在试图找到链接时被打败了。 :D
-
@Mark - Eric 的观点提出了一些我不知道的好观点。实际上,我将这篇文章的比较器从使用 System.Integer32.CompareTo() 更改了,因为我认为它可能更容易理解。我想我应该离开它。
-
@Mark 哇,我希望我能为那个链接 +1 你。我一直认为减法是一种方便的“计算机”方式来表示比较。
glow.levelUp();谢谢!
标签: c# sorting arraylist stability