C# 如何使用自定义IComparer强制对ArrayList进行稳定排序?
根据: 要执行稳定排序,必须实现自定义IComparer 接口 但据报道 文档似乎在说的是 可以使用ArrayList获得稳定的排序。排序是使用 不知何故,“知道”被比较项目的指数(一个 可以想象通过让它运行一个初始传递来实现这一点 集合),并将该信息用作 其他方面相等的元素C# 如何使用自定义IComparer强制对ArrayList进行稳定排序?,c#,sorting,arraylist,stability,C#,Sorting,Arraylist,Stability,根据: 要执行稳定排序,必须实现自定义IComparer 接口 但据报道 文档似乎在说的是 可以使用ArrayList获得稳定的排序。排序是使用 不知何故,“知道”被比较项目的指数(一个 可以想象通过让它运行一个初始传递来实现这一点 集合),并将该信息用作 其他方面相等的元素 那么,有人知道如何正确地实现一个IComparer,它以某种方式“知道”正在比较的项目的索引吗?您可以构建类似的东西(从中借用代码) 及 请注意,在框架4.5中对排序进行了更改,这可能会更改“相等”项的顺序。如果我在框架4
那么,有人知道如何正确地实现一个IComparer,它以某种方式“知道”正在比较的项目的索引吗?您可以构建类似的东西(从中借用代码) 及 请注意,在框架4.5中对排序进行了更改,这可能会更改“相等”项的顺序。如果我在框架4中运行此代码,我会得到:
Not stable
Item 6 (1)
Item 4 (1)
Item 0 (1)
Item 2 (2)
Item 3 (3)
Item 1 (3)
Item 5 (4)
Stable
Item 0 (1)
Item 4 (1)
Item 6 (1)
Item 2 (2)
Item 1 (3)
Item 3 (3)
Item 5 (4)
我试图将此代码发布到.NETFiddle,但它不允许使用Framework4。
您也可以使用稳定的。出于好奇,为什么不使用通用的
列表而不是数组列表呢?“有人知道如何正确实现IComparer吗…”是的。很多人可能是这样。可能最简单的方法是创建一个新的元组集合,其中一个元素是要排序的对象,另一个是对象的原始索引。然后使用索引作为连接断路器,正如现有堆栈溢出答案中所述。你试过什么吗?你具体需要什么帮助?堆栈溢出不是“给我代码”站点。请自己努力写一个比较器;如果需要,可以用一个好的、具体的问题发布一个新问题。@vc74我想使用List,但List只提供OrderBy(),OrderBy()创建一个新的排序列表,而不是直接排序,因此我尝试找到一个直接排序的解决方案。@PeterDuniho我发现没有必要发布我在问题中尝试过的代码,因为我尝试的代码与我已经链接的链接(&msdn docs)@123iamking的代码类似,所以很容易使用Linq的OrderBy
并修改原始列表(list=list.OrderBy(…).ToList()
)这也使它成为一个可行的选择。您应该尝试在任何实际包含重复元素的输入上测试代码。@PeterDuniho您介意提供更多关于哪里有错误的详细信息吗?对不起,我应该更具体一些。因为您已选择使用字典来维护地图,所以只有在正在排序的项目本身未实现IEquatable
且未覆盖GetHashCode()
和Equals()
时,代码才会起作用。许多类型,甚至那些需要自定义比较器的类型,都可以。(另外,七个元素还不足以证明/证明稳定与不稳定……这几个元素足以从一个不稳定的排序中得到一个看似稳定的结果,尽管这不是这里的问题。)@123iamking是的,我在4.5上得到了同样的结果。这可能是由于算法从快速排序改为内省排序。请注意,内省排序也不稳定,但似乎在这个特定集合中给出了稳定的结果。@123i请注意最后一点,Linq的OrderBy
是稳定的,可能是更好的选择。我有一段时间没有使用ArrayList
,上面代码中的施法量让人觉得很痛苦;)
class Item
{
public int Id { get; }
public string Description { get; }
public Item(int id, string description)
{
Id = id;
Description = description;
}
}
class ItemComparer : IComparer
{
public int Compare(object x, object y) => ((Item)x).Id.CompareTo(((Item)y).Id);
}
class Program
{
static void Main(string[] args)
{
var items = new ArrayList()
{
new Item(1, "Item 0 (1)"),
new Item(3, "Item 1 (3)"),
new Item(2, "Item 2 (2)"),
new Item(3, "Item 3 (3)"),
new Item(1, "Item 4 (1)"),
new Item(4, "Item 5 (4)"),
new Item(1, "Item 6 (1)")
};
Console.WriteLine("Not stable");
SortAndDisplay((ArrayList)items.Clone(), new ItemComparer());
Console.WriteLine("Stable");
SortAndDisplay((ArrayList)items.Clone(),
new StableComparer(items, new ItemComparer()));
}
static void SortAndDisplay(ArrayList items, IComparer comparer)
{
items.Sort(comparer);
foreach (var item in items)
{
Console.WriteLine(((Item)item).Description);
}
}
}
Not stable
Item 6 (1)
Item 4 (1)
Item 0 (1)
Item 2 (2)
Item 3 (3)
Item 1 (3)
Item 5 (4)
Stable
Item 0 (1)
Item 4 (1)
Item 6 (1)
Item 2 (2)
Item 1 (3)
Item 3 (3)
Item 5 (4)