通常还有删除、添加操作,这里就不提了。
假定如下类型,以Index
存储位置信息:
c#public class Item{ public int Index {get;set;} public int Name {get;set;} }
现在有许多排好序的数据:
c#var list = new List<Item>{ new Item{Index=0,Name="item 0"}, new Item{Index=1,Name="item 1"}, new Item{Index=2,Name="item 2"}, new Item{Index=3,Name="item 3"}, new Item{Index=4,Name="item 4"}, //..... };
上移、下移
上移、下移很简单,只需交换相邻两个的Index值,如果要更新到数据库,需要保存这两项。
c#//上移 item2 var index = item2.Index; item2.Index = item1.Index; item1.Index = index; //这里item1通常是这么获取:list[ list.IndexOf(item2)-1 ] //list.OrderBy(x=>x.Index) //下移 item3 var index = item3.Index; item3.Index = item4.Index; item4.Index = index; //list.OrderBy(x=>x.Index)
置顶、置底
这里有个条件,是否要保证
Index
的连续性,和是否允许Index
以负数保存。
保证
Index
的连续性,在置顶和置底的时候需要重新排序(受影响的项,需要更新到数据库的项)c#//置顶 item3 var index = item3.Index; item3.Index = 0; // 为0而不是-1,是因为如果是-1,受影响的会是其他所有项 for(int i = 0; i < index; i++) // 受影响的只有在item3之前的项 list[i].index += 1; //下移一位 //list.OrderBy(x=>x.Index) //置底 item3 var index = item3.Index; item3.Index=list.Last().Index; for(int i = index+1; i < list.Count; i++) // 受影响的只有在item3之后的项 list[i].index -= 1; //上移一位 //list.OrderBy(x=>x.Index)
不保证
Index
连续性,Index
可以为负数,只需修改要改动项的Index
即可,保存也只保存这一项。c#//置顶 item3 var index = item3.Index; var first = list.First(); item3.Index = first.Index - 1; //list.OrderBy(x=>x.Index) //置底first改成last即可
Index
不连续,但不可以为负数。这种情况其实也很简单,
int
类型的最大值是2147483647,我们可以取中间的一个值,作为我们排序的起始值,即我们新建的第一条Item
的Index
值。这样无论是置顶或置底,都可能需要几百万、几千万次,才能触顶或触底。一般这种置顶置底操作都是人工,所以不可能触底的,真的触底了,也可以重新排序一次。
这里只是作为讨论,实际场景中,有置顶需求的内容,条目不会太多。
其他
这里Index
用int
只是为了方便计算,其他类型都行,像string
和DateTime
,看实际需求,也经常和其他字段配合使用。