像C#中的另一个数组一样订购一个数组
像下面这样采用数组的最佳算法是什么:
A {0,1,2,3}
我希望订购它像下面的数组:
B {3,1,0,2}`
有任何想法吗?
解决方案
回答
因此,如果我们有两个数组,并且它们以不同的顺序保存相同的数据,则只需执行以下操作:
A = B
我怀疑这不是情况,所以我认为我们需要更多信息。
回答
在我们给出的示例(一个数字数组)中,重新排序A没有意义,因为我们可以只使用B。
因此,大概这些是我们想要按其属性之一排序的对象数组。
然后,我们将需要一种基于相关属性(如哈希表)在A中查找项目的方法。然后,我们可以迭代B(按所需顺序),并对A中的相应元素进行操作。
回答
两个数组都包含相同的值(或者几乎相同),但我需要强制它们采用相同的顺序。例如,在数组A中,值" 3045"在索引位置4中,而在数组B中,其值在索引位置1中。我想对B重新排序,以使相似值的索引位置与A相同。
回答
如果它们几乎相同,那么这里是一些伪代码:
Make an ArrayList Copy the contents of the smaller array to the arraylist for each item I in the larger array FInd I in the ArrayList Append I to a new array Remove I from the arraylist
回答
我们需要做的是确定B的顺序,然后将其应用于A。一种实现方法是取消B的顺序,并跟踪沿途发生的事情。然后,我们可以对A做相反的操作。
这是一些粗略的C(对不起,我实际上还没有运行过)...
复印一份B:
List<int> B2 = new List<int>(B);
现在,使用记录掉期的排序函数对其进行排序:
List<KeyValuePair<int,int>> swaps = new List<KeyValuePair<int,int>>(); B2.Sort( delegate( int x, int y ) { if( x<y ) return -1; if( x==y ) return 0; // x and y must be transposed, so assume they will be: swaps.Add( new KeyValuePair<int,int>(x,y) ); return 1; });
现在以相反的顺序将交换应用于A:
swaps.Reverse(); foreach( KeyValuePair<int,int> x in swaps ) { int t = A[x.key]; A[x.key] = A[x.value]; A[x.value] = t; }
根据内置排序算法的工作方式,我们可能需要自己滚动。诸如合并排序之类的非破坏性操作应该可以为我们提供正确的结果。
回答
可以使用Dictionary解决问题,使元素之间的关系根本不取决于排序顺序吗?
回答
这是比较器的实现(使用LINQ,但可以轻松地适应较早的.net版本)。我们可以将其用于任何排序算法,例如Array.Sort,Enumerable.OrderBy,List.Sort等。
var data = new[] { 1, 2, 3, 4, 5 }; var customOrder = new[] { 2, 1 }; Array.Sort(data, new CustomOrderComparer<int>(customOrder)); foreach (var v in data) Console.Write("{0},", v);
结果为`2,1,3,4,5',customOrder中未列出的任何项目都以给定类型的默认值放在末尾(除非提供了后备比较器)
public class CustomOrderComparer<TValue> : IComparer<TValue> { private readonly IComparer<TValue> _fallbackComparer; private const int UseDictionaryWhenBigger = 64; // todo - adjust private readonly IList<TValue> _customOrder; private readonly Dictionary<TValue, uint> _customOrderDict; public CustomOrderComparer(IList<TValue> customOrder, IComparer<TValue> fallbackComparer = null) { if (customOrder == null) throw new ArgumentNullException("customOrder"); _fallbackComparer = fallbackComparer ?? Comparer<TValue>.Default; if (UseDictionaryWhenBigger < customOrder.Count) { _customOrderDict = new Dictionary<TValue, uint>(customOrder.Count); for (int i = 0; i < customOrder.Count; i++) _customOrderDict.Add(customOrder[i], (uint) i); } else _customOrder = customOrder; } #region IComparer<TValue> Members public int Compare(TValue x, TValue y) { uint indX, indY; if (_customOrderDict != null) { if (!_customOrderDict.TryGetValue(x, out indX)) indX = uint.MaxValue; if (!_customOrderDict.TryGetValue(y, out indY)) indY = uint.MaxValue; } else { // (uint)-1 == uint.MaxValue indX = (uint) _customOrder.IndexOf(x); indY = (uint) _customOrder.IndexOf(y); } if (indX == uint.MaxValue && indY == uint.MaxValue) return _fallbackComparer.Compare(x, y); return indX.CompareTo(indY); } #endregion }