Csharp/C#教程:C#给定所需的订单需要空间有效的列表重新排序或排序分享


C#给定所需的订单需要空间有效的列表重新排序或排序

我的目标是:给定一个条目列表和一个所需的顺序,根据这个顺序重新排列条目列表。 该列表将非常大,因此空间效率非常重要。

例如:

List data = ReadDataFromSomeWhere(); // data => [a, b, c]; List ordering = RandomPermutation(data.Count); // ordering => [2, 1, 3]; data.ReOrderBy(ordering); // data => [b, a, c]; 

我可能会弄错,但似乎最直接和节省空间的解决方案是通过排序对数据进行排序/ 排序 。 或更一般地说:

给出两个列表:A,B有没有办法按B排序A? 该function基本上与以下相同: Array.Sort<(Of )>)(array[]()[], array[]()[])

想到的一种方法是创建一个由A和B组成的新数据类型,即。 配对,然后按B值排序:

 List A; List B; Assert(A.Count == B.Count); var C = A.Select( (a,idx) => new Pair(B[idx],a)).OrderBy(c => c.First); A = C.Select(x => x.Second).ToList(); 

但是,我希望这样做尽可能节省空间( select猜测和tolist()调用我估计都很昂贵 ),因此必须进行大量的就地排序。 为此,有没有办法为A.Sort()编写一个比较器,它引用B?

解释order数组的方法有两种,一种是列出每个元素的源索引,另一种是列出每个元素的目标索引。 我不确定你指的是哪一个。

重新排序给定目的地列表的列表非常简单:

 // Sets list[destination[i]] = list[i] for all i. Clobbers destination list. void ReorderByDestination(List list, List destination) { for (int i = 0; i < list.Count; i++) { while (destination[i] != i) { int d = destination[i]; T t = list[d]; // save element in destination slot int t_d = destination[d]; // and its own destination list[d] = list[i]; // move element to destination destination[d] = d; // and mark it as moved list[i] = t; // store saved element in slot i destination[i] = t_d; // ... and its destination } } } 

重新排序列表给出一个源列表(这是我认为你想要的)有点困难,你只需要先颠倒排列。

 // Sets list[i] = list[source[i]] for all i. Clobbers source list. void ReorderBySource(List list, List source) { InvertPermutation(source); ReorderByDestination(list, source); } 

有已知的就地置换反转例程,我发现第一个是SUBSET中的perm_inv。

通常,您不需要反转排列,而是修改生成源列表的任何内容以生成目标列表。

最有效的重新排序算法可能是某种forms的惰性评估。 您可以创建一个IList实现,使用数据列表和排序列表动态返回“虚拟重新排序”序列中的值,而不是按新顺序重新计算序列。

惰性模型的好处是执行双重查找在性能方面可以忽略不计,并且不需要重新排序整个列表以便开始返回值。 它还可能允许相同的值列表以多个顺序呈现而不复制基础列表。 当然,如果要确保对原始列表(或排序)的更改不会影响动态排序列表,您可以更改实现以复制列表。

这是一个代码示例(未经测试)。

注意: 为了简单起见,我已经从您的示例稍微更改了实现,以使用基于0的索引(而不是基于1的索引)。 但是如果需要,可以很容易地将代码转换为使用基于1的索引。

 public DynamicallyOrderedList : IList { private readonly IList m_Values; private readonly IList m_Order; public DynamicallyOrderedList( IList valueList, IList ordering ) { if( valueList == null || ordering == null ) throw new ArgumentNullException(); if( valueList.Count != ordering.Count ) throw new InvalidArgumentException("Lists are not of same size."); // assumes ordering list has distinct values ranging from 0 to Count-1 m_Values = valueList; m_Order = ordering; } // IList Implementation // for simplicity, don't allow addition, removal or clearing of items // these could, however be implemented to add items to the end of the list // and remove them by collapsing the ordering list. // Left as an exercise for the reader :-) public void Add( T item ) { throw new NotSupportedException(); } public void Insert(int index, T item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public void Remove( T item ) { throw new NotSupportedException(); } public void RemoveAt( int index ) { throw new NotSupportedException(); } public T this[int index] { get { if( index > m_Values.Count ) throw new ArgumentOutOfRangeException("index"); return m_Values[m_Order[index]]; } set { if( index > m_Values.Count ) throw new ArgumentOutOfRangeException("index"); m_Values[m_Order[index]] = value; } } public int Count { get { return m_Values.Count; } } public bool Contains( T item ) { return m_Values.Contains( item ); } public bool IndexOf( T item ) { return m_Order[m_Values.IndexOf( item )]; } // Enumerator that returns items in the order defined by m_Order public IEnumerator GetEnumerator() { // use generator syntax to simplify enumerator implementation foreach( var index in m_Order ) yield return m_Values[index]; } public void CopyTo( T[] array, int arrayIndex ) { foreach( var item in this ) array[arrayIndex++] = item; } 

}

你的ReorderBy()函数然后变成:

 public static class ReorderByExt { public static IList ReorderBy( this IList list, IList order ) { return new DynamicallyOrderedList( list, order ); } } 

如果您需要将动态排序列表具体化为常规列表,则可以使用以下(将在O(n)时间运行并且不会创建不必要的数据副本):

上述就是C#学习教程:C#给定所需的订单需要空间有效的列表重新排序或排序分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 var staticallyOrderedList = originalList.ReorderBy( ordering ).ToList(); 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/996962.html

(0)
上一篇 2021年12月25日
下一篇 2021年12月25日

精彩推荐