这可能是一个简单的问题。假设我有一个小型列表,大约有20-50个条目。类似的东西:
class Item
{
int ItemNumber;
int OrderNumber;
string Name;
}
stored in something like
List<Item>
这存储在OrderNumber从1,2,3,4,...... 50开始的通用列表或数组中。为了简化操作,我们假设OrderNumber已经在其他地方通过QuickSort在List中排序(除非这会使事情变得更复杂)。
假设我想将Item.OrderNumber = 30移动到Item.OrderNumber = 20或类似的地方。当我这样做时,现在需要移动20以上的所有东西,以便旧的20现在是21,21现在是22等等,直到我达到30.它还需要反过来,所以当Item.OrderNumber = 30移动到Item.OrderNumber = 34,一切都必须向下移动。
我正在考虑将列表冒泡几次,但我希望有更好的方法来做到这一点。虽然列表大小很小,但这需要为各种不同的事情做很多事情。
编辑:只是为了让你知道。结果最终必须存储在某种类型的事务中的数据库中。答案 0 :(得分:2)
是否必须是List<T>
?如果没有,您可以考虑使用SortedList<TKey, TValue>
或SortedDictionary<TKey, TValue>
。然后,您可以使用OrderNumber作为键,只需让集合完成工作。
对于List<T>
,您可以List<T>.BinarySearch
使用IComparer<T>
与适当的int position = list.BinarySearch(newOrder, orderComparer);
list.Insert(position >= 0 ? position : ~position, newOrder);
进行比较,并按订单号进行比较 - 您可以:
IComparer<T>
您可以在整个代码中使用相同的{{1}}实例,因为它将是无状态的。
编辑:此解决方案不会更改Robert Wagner's answer中建议的任何其他条目的OrderNumber。
答案 1 :(得分:1)
如果我理解正确,你试图将OrderNumber保持在对象内(无论出于何种原因),但需要能够将新对象添加到列表中并使所有其他对象调整其OrderNumber以使新的一个合适。此外,列表中项目的实际顺序也不一定重要。
这可以通过包装列表并实现您自己的操作(移动/插入/删除功能,执行以下操作来完成):
插入强> 循环遍历所有项目并将ordernumber增加1,其中ordernumber> = new item的订单号 将项目添加到列表
删除强> 删除该项目 循环遍历所有项目并将ordernumber减少一个ordernumber&gt;已删除商品的订单号
<强>移动强> 删除该项目 重新编号该项目 插入项目
答案 2 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Class1
{
static void Main()
{
var beatles = new LinkedList<string>();
beatles.AddFirst("John");
LinkedListNode<string> nextBeatles = beatles.AddAfter(beatles.First, "Paul");
nextBeatles = beatles.AddAfter(nextBeatles, "George");
beatles.AddAfter(nextBeatles, "Ringo");
LinkedListNode<string> paulsNode = beatles.NodeAt(1); // middle's index
LinkedListNode<string> recentHindrance = beatles.AddBefore(paulsNode, "Yoko");
recentHindrance = beatles.AddBefore(recentHindrance, "Aunt Mimi");
beatles.AddBefore(recentHindrance, "Father Jim");
Console.WriteLine("{0}", string.Join("\n", beatles.ToArray()));
Console.ReadLine();
}
}
public static class Helper
{
public static LinkedListNode<T> NodeAt<T>(this LinkedList<T> l, int index)
{
LinkedListNode<T> x = l.First;
while ((index--) > 0) x = x.Next;
return x;
}
}
答案 3 :(得分:0)
如果你使用双链表,你可以在19之后或20之前将OrderNumber = 30非常便宜地插入到该位置。然后迭代到小于30的OrderNumber并将每个订单增加1。反向移动列表中较高的项目。
答案 4 :(得分:0)
在填充列表后进行排序,然后通过粘贴到最后来填充。如果您需要随时进行分类,请按照Skeet的说法进行分类。