最简单的方法重新排序一个序列
本文关键字:一个 方法 新排序 最简单 排序 | 更新日期: 2023-09-27 18:18:44
考虑4个(最多100个)类A的实例,在List中有一个int属性Order。
a0.Order is 0
a1.Order is 1
a2.Order is 2
a3.Order is 3
现在需要更改Order属性,以便a0插入在a3之前(或在列表中的任何索引-可以在开始,结束或中间)
结果应该是:
a0.Order is 2
a1.Order is 0
a2.Order is 1
a3.Order is 3
注意,这是一个列表,列表的实际物理顺序无关紧要,只有属性被改变了。
项目的数量不只是改变"顺序"。
实现这一点最简单的方法是什么?
Order属性不应该是整数,而应该是小数。您可以轻松地更改该值,然后按其排序,以任意顺序检索条目。新值为前一值和后一值之间的中点。
注:然后,您只需更改列表中要重新定位的项目的Order属性。
你可以这样做:
void MoveAndUpdateOrder(List<A> list, A item, int positionToInsert)
{
// Order elements
var ordered_list = list.OrderBy(a => a.Order).ToList();
// Remove and insert at the proper position
ordered_list.Remove(item);
ordered_list.Insert(positionToInsert, item);
// Update the Order properties according to it's current index
for ( int i = 0; i < ordered_list.Count; i++ )
ordered_list[i].Order = i;
}
然后像这样调用它:
var a0 = new A { Order = 0 };
var a1 = new A { Order = 1 };
var a2 = new A { Order = 2 };
var a3 = new A { Order = 3 };
var list = new List<A>
{
a0, a1, a2, a3
};
MoveAndUpdateOrder( list, a0, 2 );
我们必须区分向上移动元素(到列表的末尾)还是向下移动元素(到列表的开始)。我们定义两个序号i
和k
,其中i < k
.
将元素i
向上移动到k
:i
以下和k
以上的订单不受影响。i+1 ... k
的阶数减少一阶,i
变为k
。
A moving = list.Where(a => a.Order == i);
foreach (A x in list.Where(a => a.Order > i && a.Order <= k)
{
x.Order--;
}
moving.Order = k;
移动元素k
到i
:i
以下和k
以上的订单不受影响。i ... k-1
的阶数增加1,k
变为i
。
A moving = list.Where(a => a.Order == k);
foreach (A x in list.Where(a => a.Order >= i && a.Order < k)
{
x.Order++;
}
moving.Order = i;
如果你能负担得起,我会给它们编号,中间间隔:
a0.Order is 10
a1.Order is 20
a2.Order is 30
a3.Order is 40
通过这种方式,你可以简单地通过选择一个数字来重新排序。
a0.Order is 35
a1.Order is 20
a2.Order is 30
a3.Order is 40
经过一些迭代后,您可能在某些插入点上没有gabs。对于100件物品,您可以简单地重置所有订单号,使其具有相同的gabs。
是否可以将项目保存在列表中,并从列表中项目的物理顺序暗示Order
属性?
给定一个没有 order属性的 你可以为 可以这样使用 然后当你需要Item
类,如下所示:class Item
{
public readonly string Value;
public Item(string value)
{
Value = value;
}
public override string ToString()
{
return Value;
}
}
Items
写一个简单的集合类,它有一个Move()
方法,可以让你把一个项目从一个索引移动到另一个索引:class Items: IEnumerable<Item>
{
private readonly List<Item> _items = new List<Item>();
public void Add(Item item)
{
_items.Add(item);
}
public int Count
{
get { return _items.Count; }
}
public void Move(int oldIndex, int newIndex)
{
Item item = _items[oldIndex];
_items.RemoveAt(oldIndex);
_items.Insert(newIndex, item);
}
IEnumerator<Item> IEnumerable<Item>.GetEnumerator()
{
return _items.GetEnumerator();
}
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
Items
:var items = new Items
{
new Item("a0"),
new Item("a1"),
new Item("a2"),
new Item("a3")
};
// ...
items.Move(0, 2); // Move the item at index 0 to index 2.
Order
时,你可以从列表的物理顺序中合成它,如下所示:var orderedItems = items.Select((item, index) => new { Item = item, Order = index});
我为你编写了算法,它使用排序和LinkedList集合:
using System;
using System.Collections.Generic;
namespace OrderExample {
public class A {
public int Order { get; set; }
}
public class Program {
// Change order so that a is ordered between b and c.
public static void SetOrder(List<A> list, A a, A b, A c) {
list.Sort((x, y) => x.Order.CompareTo(y.Order));
var linkedList = new LinkedList<A>(list);
var bNode = linkedList.Find(b);
if (bNode != null) {
linkedList.Remove(a);
linkedList.AddAfter(bNode, a);
var i = 0;
foreach (var value in linkedList) {
value.Order = i++;
}
}
}
static void Main() {
var a0 = new A {Order = 0};
var a1 = new A {Order = 1};
var a2 = new A {Order = 2};
var a3 = new A {Order = 3};
var list = new List<A> {a0, a1, a2, a3};
SetOrder(list, a0, a2, a3);
foreach (var a in list) {
Console.Out.WriteLine(a.Order);
}
Console.ReadKey();
}
}
}