假设您需要保留一个更改列表,该列表可能包含重复值的项目,已排序。例如,您有[99,99,90,89],但第4项的值已更改为91.您可能希望它为[99,99,91,90],但您不希望要更改的第一个和第二个项目的顺序。
我使用了Sort()
方法但似乎它可能会更改上面示例的第一项和第二项的顺序。有没有办法阻止它并保持具有相同值的项目的相对顺序?
如果您无法想到为什么需要这样做,请假设进度列表。列表中的项目每秒更新一次。当项目按进度排序时,您可能希望相同进度的项目不断更改其相对位置。
我已经创建了一个示例代码来测试它。目标是达到Debug.WriteLine("No change");
。
public void Start()
{
var list = new List<Item>();
var ran = new Random();
const int nItems = 30;
for (int i = 0; i < nItems; i++)
{
var name = "Item " + (list.Count + 1);
var item = new Item(name, ran.Next(0, 10));
list.Add(item);
}
var sorter = new ItemComparer();
var snapshot = new Item[nItems];
for (int nSort = 0; nSort < 10000; nSort++)
{
list.CopyTo(snapshot);
list.Sort(sorter);
if (nSort == 0)
{
//Sorted for the first time, so the snapshot is invalid.
continue;
}
for (int pos = 0; pos < nItems; pos++)
{
if (snapshot[pos] != list[pos])
{
Debug.WriteLine($"Order changed at position {pos} after {nSort} sorts.");
PrintChangedLocation(list, snapshot, pos);
return;
}
}
}
Debug.WriteLine("No change");
}
private static void PrintChangedLocation(List<Item> list, Item[] snapshot, int changedLocation)
{
Debug.WriteLine($"Before\t\t\tAfter");
for (int pos = 0; pos < list.Count; pos++)
{
var before = snapshot[pos];
var after = list[pos];
Debug.Write($"{before.Name} = {before.Progress}");
Debug.Write($"\t\t{after.Name} = {after.Progress}");
if (pos == changedLocation)
{
Debug.Write(" <----");
}
Debug.WriteLine("");
}
}
class Item
{
public string Name;
public float Progress;
public Item(string name, float progress)
{
Name = name;
Progress = progress;
}
}
class ItemComparer : IComparer<Item>
{
int Direction = -1;
public int Compare(Item x, Item y)
{
return Direction * (int)(x.Progress - y.Progress);
}
}
示例输出:
Order changed at position 12 after 1 sorts.
Before After
Item 7 = 9 Item 7 = 9
Item 24 = 9 Item 24 = 9
Item 30 = 8 Item 30 = 8
Item 4 = 8 Item 4 = 8
Item 19 = 8 Item 19 = 8
Item 27 = 7 Item 27 = 7
Item 5 = 7 Item 5 = 7
Item 25 = 7 Item 25 = 7
Item 20 = 7 Item 20 = 7
Item 26 = 6 Item 26 = 6
Item 14 = 6 Item 14 = 6
Item 1 = 6 Item 1 = 6
Item 28 = 5 Item 2 = 5 <----
Item 2 = 5 Item 12 = 5
Item 12 = 5 Item 28 = 5
Item 11 = 4 Item 11 = 4
Item 6 = 4 Item 6 = 4
Item 13 = 3 Item 13 = 3
Item 3 = 3 Item 3 = 3
Item 21 = 3 Item 21 = 3
Item 10 = 3 Item 10 = 3
Item 18 = 3 Item 18 = 3
Item 22 = 2 Item 22 = 2
Item 29 = 2 Item 29 = 2
Item 23 = 1 Item 23 = 1
Item 8 = 1 Item 8 = 1
Item 17 = 1 Item 17 = 1
Item 16 = 0 Item 9 = 0
Item 9 = 0 Item 16 = 0
Item 15 = 0 Item 15 = 0
答案 0 :(得分:0)
要考虑的一个选择是改变:
list.Sort(sorter);
为:
list = list
.Select((item, index) => new { item, index})
.OrderBy(z => z.item, sorter)
.ThenBy(z => z.index)
.Select(z => z.item)
.ToList();
这允许您按照比较器然后按其在List
中的位置进行排序 - 从而保持相对顺序。