Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重新订购IList<;T>;使用插入和删除的最小数量_C#_Sorting - Fatal编程技术网

C# 重新订购IList<;T>;使用插入和删除的最小数量

C# 重新订购IList<;T>;使用插入和删除的最小数量,c#,sorting,C#,Sorting,我需要一个包含两个参数的扩展方法:targetIList和一个自定义比较器 public static void CustomSort<T>( IList<T> target, IComparer<T> comparer ) { ... } publicstaticvoidcustomsort(IList目标,IComparer比较器) { ... } 扩展方法的工作是按照自定义比较器指示的顺序排列目标元素 以下是一些不起作用的解决方案: Lis

我需要一个包含两个参数的扩展方法:target
IList
和一个自定义比较器

public static void CustomSort<T>( IList<T> target, IComparer<T> comparer )
{
    ...
}
publicstaticvoidcustomsort(IList目标,IComparer比较器)
{
...
}
扩展方法的工作是按照自定义比较器指示的顺序排列目标元素

以下是一些不起作用的解决方案:

  • List.Sort
    进行就地排序,这基本上就是我想要的。但我不能假设target的具体类型是
    List
  • LINQ提供了一些解决方案,但不幸的是,它们将结果输出为新的可枚举项,而不是修改目标列表

相反,我需要调用目标的
Remove
Insert
方法,以便将其元素按正确的顺序排列。目标列表可能是可见的,因此解决方案的删除和插入操作不应超过获得所需顺序所需的次数,这一点很重要。

如前所述,注释表明这实际上是一个难题。那么,如果我们从不同的角度来看待这个问题呢:

  • 为什么这一系列的观察者要花这么长时间?他们应该只做快速的事情来回应个人的变化。例如,如果是UI更改,则可以等到下一次重新绘制UI后再考虑更改。这将使整个重新订购一次完成。或
  • 使用类似这样的方法,以便在可观察的集合上有一个
    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
    如前所述,评论表明这实际上可能是一个难题。那么,如果我们从不同的角度来看待这个问题呢:

  • 为什么这一系列的观察者要花这么长时间?他们应该只做快速的事情来回应个人的变化。例如,如果是UI更改,则可以等到下一次重新绘制UI后再考虑更改。这将使整个重新订购一次完成。或
  • 使用类似这样的方法,以便在可观察的集合上有一个
    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();
    //此时,“移动”是从源位置到目标位置的移动列表。
    //我们列举了这一点,并按顺序应用这些动作。
    //要做到这一点,我们需要擦伤