Заказать массив, как другой массив в C # - PullRequest
1 голос
/ 04 сентября 2008

Какой лучший алгоритм для получения массива, как показано ниже:

A {0,1,2,3}

Я ожидал заказать его как массив ниже:

B {3,1,0,2}

Есть идеи?

Ответы [ 7 ]

6 голосов
/ 04 сентября 2008

Итак, если у вас есть два массива и они содержат одни и те же данные в разном порядке, просто сделайте это:

A = B

Я подозреваю, что это не ваша ситуация, поэтому я думаю, что нам нужно больше информации.

3 голосов
/ 04 сентября 2008

Что вам нужно сделать, это определить порядок B, а затем применить этот порядок к A. Один из способов сделать это - отменить порядок B и отслеживать, что происходит на этом пути. Тогда вы можете сделать обратное к А.

Вот несколько отрывочных 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;
}

В зависимости от того, как работает встроенный алгоритм сортировки, вам может понадобиться свернуть свой собственный. Что-то неразрушающее, вроде сортировки слиянием, должно дать вам правильные результаты.

2 голосов
/ 24 ноября 2010

Вот моя реализация компаратора (использует 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
}
1 голос
/ 23 марта 2009

Может ли проблема быть решена с помощью словаря, чтобы у элементов была связь, которая вообще не определяется порядком сортировки?

1 голос
/ 04 сентября 2008

Если они почти одинаковы, то вот псевдокод:

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
1 голос
/ 04 сентября 2008

Оба массива содержат одинаковые значения (или почти так), но мне нужно заставить их быть в том же порядке. Например, в массиве A значение «3045» находится в позиции индекса 4, а в массиве B - в позиции индекса 1. Я хочу изменить порядок B таким образом, чтобы позиции индекса одинаковых значений были такими же, как A.

1 голос
/ 04 сентября 2008

В приведенном вами примере (массив чисел) нет смысла переупорядочивать A, поскольку вы можете просто использовать B.

Итак, предположительно, это массивы объектов, которые вы хотите упорядочить по одному из их свойств.

Затем вам потребуется способ поиска элементов в A на основе рассматриваемого свойства (например, хеш-таблицы). Затем вы можете выполнить итерацию B (которая находится в нужной последовательности) и работать с соответствующим элементом в A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...