### 使用最小插入数和删除数重新排序IList <t> </t>

``````public static void CustomSort<T>( IList<T> target, IComparer<T> comparer )
{
...
}
``````

• `List<T>.Sort`进行就地排序，这基本上就是我所追求的。但我不能假设目标的具体类型是`List<T>`
• LINQ提供了一些解决方案，但不幸的是，他们将结果输出为新的可枚举，而不是修改目标列表。

#### 3 个答案:

``````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 ) )
{
}
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 )
{
}

// finally, move the source value into its destination slot.
list[ move.Dest ] = value ;

}

return ;
}
``````

1. 为什么这个系列的观察者需要这么长时间？他们应该只根据个人变化做快速的事情。例如。如果它是用于UI更改，它可能会等到下一个UI重绘之后再关注更改。这应该让整个重新整理完成一次。或
2. 使用`ObservableRangeCollection<T>`之类的内容，以便在可观察的集合中获得`AddRange`。如果可能，一些简单的代码可以确定集合是`List<T>`还是`ObservableRangeCollection<T>`以使用`AddRange`
3. E.g。

``````public static void SmartSort<T>(IList<T> source)
{
var sortedList = source.OrderBy(x => x).ToList();
if (source.SequenceEqual(sortedList))
return;
var list = source as List<T>;
var collection = source as ObservableRangeCollection<T>;
if (list != null)
{
list.Clear();
}
else if (collection != null)
collection.ReplaceRange(sortedList);
else
{
for (int i = 0; i < source.Count; i++)
source[i] = sortedList[i];
}
}
``````

1. 使用LINQ扩展方法排序并获取一个新的List，最后隐式调用`ToList()`;

2. 然后告诉您的可观察列表暂停（不关心更改）

3. 清除您的可观察列表

4. 从linq-ordered列表中将项添加到observable列表中。

5. 告诉您的可观察列表继续观看更改

6. 观察者观察的变化数量是否有效;从算法效率的角度来看，我试试这个解决方案。您可能永远不需要进一步优化。请记住： premature optimization is the root of all evil