简体   繁体   English

像C#中的另一个数组一样订购一个数组

[英]Order an Array like another Array in C#

What is the best algorithm to take array like below: 像下面这样采用数组的最佳算法是什么:

A {0,1,2,3}

I expected to order it like array below: 我希望订购它像下面的数组:

B {3,1,0,2}

Any ideas? 有任何想法吗?

So if you have two arrays and they hold the same data just in different order then just do this: 因此,如果您有两个数组并且它们以不同的顺序保存相同的数据,则只需执行以下操作:

A = B A = B

I suspect that is not your situation so I think we need more info. 我怀疑这不是您的情况,所以我认为我们需要更多信息。

What you need to do is determine the ordering of B and then apply that ordering to A. One way to accomplish this is to undo the ordering of B and keep track of what happens along the way. 您需要做的是确定B的顺序,然后将其应用于A。一种实现方法是取消B的顺序并跟踪沿途发生的情况。 Then you can do the reverse to A. 然后,您可以对A做相反的操作。

Here's some sketchy C# (sorry, I haven't actually run this)... 这是一些粗略的C#(对不起,我实际上还没有运行它)...

Take a copy of B: 复印一份B:

List<int> B2 = new List<int>(B);

Now sort it, using a sort function that records the swaps: 现在,使用记录交换的排序功能对其进行排序:

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;
});

Now apply the swaps, in reverse order, to A: 现在以相反的顺序将交换应用于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;
}

Depending how the built-in sort algorithm works, you might need to roll your own. 根据内置排序算法的工作方式,您可能需要自己滚动。 Something nondestructive like a merge sort should give you the correct results. 诸如合并排序之类的非破坏性操作应该可以为您提供正确的结果。

Here's my implementation of the comparer (uses LINQ, but can be easily adapted to older .net versions). 这是比较器的实现(使用LINQ,但可以轻松地适应较早的.net版本)。 You can use it for any sorting algorithms such as Array.Sort, Enumerable.OrderBy, List.Sort, etc. 您可以将其用于任何排序算法,例如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);

The result is 2,1,3,4,5, - any items not listed in the customOrder are placed at the end in the default for the given type (unless a fallback comparator is given) 结果为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
}

In the example you gave (an array of numbers), there would be no point in re-ordering A, since you could just use B. 在您给出的示例(一个数字数组)中,重新排序A没有意义,因为您可以只使用B。

So, presumably these are arrays of objects which you want ordered by one of their properties. 因此,大概这些是您想要按其属性之一排序的对象数组。

Then, you will need a way to look up items in A based on the property in question (like a hashtable). 然后,您将需要一种基于相关属性(例如哈希表)在A中查找项目的方法。 Then you can iterate B (which is in the desired sequence), and operate on the corresponding element in A. 然后,您可以迭代B(按所需顺序),并对A中的相应元素进行操作。

Both array's contain the same values (or nearly so) but I need to force them to be in the same order. 两个数组都包含相同的值(或几乎相同),但我需要强制它们采用相同的顺序。 For example, in array A the value "3045" is in index position 4 and in array B it is in index position 1. I want to reorder B so that the index positions of like values are the same as A. 例如,在数组A中,值“ 3045”在索引位置4中,而在数组B中,其值在索引位置1中。我想对B重新排序,以使相似值的索引位置与A相同。

If they are nearly the same then here is some pseudo code: 如果它们几乎相同,那么这里是一些伪代码:

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

是否可以使用字典解决问题,使元素之间的关系完全不基于排序顺序?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM