C# 重新订购IList<;T>;使用插入和删除的最小数量
我需要一个包含两个参数的扩展方法:targetC# 重新订购IList<;T>;使用插入和删除的最小数量,c#,sorting,C#,Sorting,我需要一个包含两个参数的扩展方法:targetIList和一个自定义比较器 public static void CustomSort<T>( IList<T> target, IComparer<T> comparer ) { ... } publicstaticvoidcustomsort(IList目标,IComparer比较器) { ... } 扩展方法的工作是按照自定义比较器指示的顺序排列目标元素 以下是一些不起作用的解决方案: Lis
IList
和一个自定义比较器
public static void CustomSort<T>( IList<T> target, IComparer<T> comparer )
{
...
}
publicstaticvoidcustomsort(IList目标,IComparer比较器)
{
...
}
扩展方法的工作是按照自定义比较器指示的顺序排列目标元素
以下是一些不起作用的解决方案:
进行就地排序,这基本上就是我想要的。但我不能假设target的具体类型是List.Sort
List
- LINQ提供了一些解决方案,但不幸的是,它们将结果输出为新的可枚举项,而不是修改目标列表
相反,我需要调用目标的
Remove
和Insert
方法,以便将其元素按正确的顺序排列。目标列表可能是可见的,因此解决方案的删除和插入操作不应超过获得所需顺序所需的次数,这一点很重要。如前所述,注释表明这实际上是一个难题。那么,如果我们从不同的角度来看待这个问题呢:
AddRange
。一些简单的代码可以确定集合是List
还是observerangecollection
以尽可能使用AddRange
publicstaticvoidsmartsort(IList源代码)
{
var sortedList=source.OrderBy(x=>x.ToList();
if(源序列相等(分类列表))
回来
var list=源作为列表;
var collection=源作为ObserverAgeCollection;
如果(列表!=null)
{
list.Clear();
列表.添加范围(分类列表);
}
else if(集合!=null)
collection.ReplaceRange(分类列表);
其他的
{
for(int i=0;i
如前所述,评论表明这实际上可能是一个难题。那么,如果我们从不同的角度来看待这个问题呢:
AddRange
。一些简单的代码可以确定集合是List
还是observerangecollection
以尽可能使用AddRange
publicstaticvoidsmartsort(IList源代码)
{
var sortedList=source.OrderBy(x=>x.ToList();
if(源序列相等(分类列表))
回来
var list=源作为列表;
var collection=源作为ObserverAgeCollection;
如果(列表!=null)
{
list.Clear();
列表.添加范围(分类列表);
}
else if(集合!=null)
collection.ReplaceRange(分类列表);
其他的
{
for(int i=0;i
我想这样做对你有好处
我们对偏移量数组进行排序,然后确定需要应用的增量集,最后应用它们生成新排序的IList
public static void CustomSort<T>( IList<T> list , IComparer<T> comparer )
{
int[] unsorted = Enumerable.Range(0,list.Count).ToArray() ;
int[] sorted = Enumerable.Range(0,list.Count).OrderBy( x => list[x] , comparer ).ToArray() ;
var moves = sorted.Zip( unsorted , (x,y) => new{ Src = x , Dest = y , } ).Where( x => x.Src != x.Dest ).OrderBy( x => x.Src ).ToArray() ;
// at this point, moves is a list of moves, from a source position to destination position.
// We enumerate over this and apply the moves in order.
// To do this we need a scratch pad to save incomplete moves, where an existing item has
// been over-written, but it has not yet been moved into its final destination.
Dictionary<int,T> scratchPad = new Dictionary<int, T>() ; // a parking lot for incomplete moves
foreach ( var move in moves )
{
T value ;
// see if the source value is on the scratchpad.
// if it is, use it and remove it from the scratch pad.
// otherwise, get it from the indicated slot in the list.
if ( scratchPad.TryGetValue( move.Src , out value ) )
{
scratchPad.Remove( move.Src );
}
else
{
value = list[ move.Src ] ;
}
// if the destination is after the source position, we need to put
// it on the scratch pad, since we haven't yet used it as a source.
if ( move.Dest > move.Src )
{
scratchPad.Add( move.Dest , list[ move.Dest ]);
}
// finally, move the source value into its destination slot.
list[ move.Dest ] = value ;
}
return ;
}
publicstaticvoidcustomsort(IList列表、IComparer比较器)
{
int[]unsorted=Enumerable.Range(0,list.Count).ToArray();
int[]sorted=Enumerable.Range(0,list.Count).OrderBy(x=>list[x],comparer.ToArray();
var moves=sorted.Zip(unsorted,(x,y)=>new{Src=x,Dest=y,}).Where(x=>x.Src!=x.Dest).OrderBy(x=>x.Src.ToArray();
//此时,“移动”是从源位置到目标位置的移动列表。
//我们列举了这一点,并按顺序应用这些动作。
//要做到这一点,我们需要一个便笺簿来保存未完成的移动,其中一个现有项目已被删除
//它已经被改写了,但还没有进入它的最终目的地。
Dictionary scratchPad=new Dictionary();//未完成移动的停车场
foreach(var移入移动)
{
T值;
//查看源值是否在草稿行上。
//如果是,请使用它并将其从刮板上拆下。
//否则,从列表中指定的插槽获取它。
if(scratchPad.TryGetValue(move.Src,out值))
{
删除草稿行(move.Src);
}
其他的
{
value=list[move.Src];
}
//如果目标在源位置之后,我们需要放置
//它在便笺簿上,因为我们还没有使用它作为来源。
if(move.Dest>move.Src)
{
scratchPad.Add(move.Dest,list[move.Dest]);
}
//最后,将源值移动到其目标插槽中。
列表[move.Dest]=值;
}
回来
}
我想这样做对你有好处
我们对偏移量数组进行排序,然后确定需要应用的增量集,最后应用它们生成新排序的IList
public static void CustomSort<T>( IList<T> list , IComparer<T> comparer )
{
int[] unsorted = Enumerable.Range(0,list.Count).ToArray() ;
int[] sorted = Enumerable.Range(0,list.Count).OrderBy( x => list[x] , comparer ).ToArray() ;
var moves = sorted.Zip( unsorted , (x,y) => new{ Src = x , Dest = y , } ).Where( x => x.Src != x.Dest ).OrderBy( x => x.Src ).ToArray() ;
// at this point, moves is a list of moves, from a source position to destination position.
// We enumerate over this and apply the moves in order.
// To do this we need a scratch pad to save incomplete moves, where an existing item has
// been over-written, but it has not yet been moved into its final destination.
Dictionary<int,T> scratchPad = new Dictionary<int, T>() ; // a parking lot for incomplete moves
foreach ( var move in moves )
{
T value ;
// see if the source value is on the scratchpad.
// if it is, use it and remove it from the scratch pad.
// otherwise, get it from the indicated slot in the list.
if ( scratchPad.TryGetValue( move.Src , out value ) )
{
scratchPad.Remove( move.Src );
}
else
{
value = list[ move.Src ] ;
}
// if the destination is after the source position, we need to put
// it on the scratch pad, since we haven't yet used it as a source.
if ( move.Dest > move.Src )
{
scratchPad.Add( move.Dest , list[ move.Dest ]);
}
// finally, move the source value into its destination slot.
list[ move.Dest ] = value ;
}
return ;
}
publicstaticvoidcustomsort(IList列表、IComparer比较器)
{
int[]unsorted=Enumerable.Range(0,list.Count).ToArray();
int[]sorted=Enumerable.Range(0,list.Count).OrderBy(x=>list[x],comparer.ToArray();
var moves=sorted.Zip(unsorted,(x,y)=>new{Src=x,Dest=y,}).Where(x=>x.Src!=x.Dest).OrderBy(x=>x.Src.ToArray();
//此时,“移动”是从源位置到目标位置的移动列表。
//我们列举了这一点,并按顺序应用这些动作。
//要做到这一点,我们需要擦伤