2008-09-04 9 views
1

Quel est le meilleur algorithme pour prendre tableau comme ci-dessous:Commander un tableau comme un autre tableau en C#

A {0,1,2,3}

Je pensais commander comme tableau ci-dessous:

B {3,1,0,2}

Tous des idées?

+0

pouvez-vous dire si tout éléments dans A existeront dans B? Je suppose que cela n'aurait pas d'importance si certains éléments n'étaient pas dans A. la possibilité inverse donnerait quelque chose comme un résultat indéfini - bien que vous puissiez simplement les laisser tomber à la fin. – zanlok

Répondre

6

Donc, si vous avez deux tableaux et ils ont les mêmes données que dans un ordre différent alors faites ceci:

A = B

Je soupçonne que ce n'est pas votre situation, donc je pense que nous avons besoin de plus d'informations .

1

Dans l'exemple que vous avez donné (un tableau de nombres), il n'y aurait pas de point de réordonnancement A, puisque vous pouvez simplement utiliser B.

Ainsi, ce sont probablement des tableaux d'objets que vous souhaitez commandés par l'une de leurs propriétés. Ensuite, vous aurez besoin d'un moyen de rechercher des éléments dans A en fonction de la propriété en question (comme une hashtable). Ensuite, vous pouvez parcourir B (qui est dans la séquence désirée) et opérer sur l'élément correspondant dans A.

1

Les deux tableaux contiennent les mêmes valeurs (ou presque) mais je dois les forcer à être dans le même ordre . Par exemple, dans le tableau A, la valeur "3045" est dans la position d'index 4 et dans le tableau B, dans la position d'index 1. Je veux réorganiser B de sorte que les positions d'index soient identiques à A.

+0

S'il vous plaît ne pas clarifier votre question avec une réponse, modifier votre question initiale pour inclure les informations supplémentaires. Parce que les réponses sont triées par vote, cela signifie que votre clarification sera toujours en bas. Cela signifie également que vous obtenez la réputation de clarifier votre réponse, pas bon. –

1

Si elles sont presque même alors voici quelques 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 
3

ce que vous devez faire est de déterminer l'ordre de B puis appliquer cette commande à A. Une façon d'y arriver est d'annuler la commander B et garder une trace de ce qui se passe en cours de route. Ensuite, vous pouvez faire l'inverse A.

Voici quelques peu précis C# (désolé, je ne l'ai pas fait courir ce) ...

Prenez une copie de B:

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

maintenant Trier , en utilisant une fonction de tri qui enregistre les 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; 
}); 

maintenant les swaps appliquent, dans l'ordre inverse, à 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; 
} 

Selon le fonctionnement de l'algorithme de tri intégré, vous devrez peut-être rouler le vôtre. Quelque chose de non destructif comme un tri de fusion devrait vous donner les bons résultats.

+0

J'aime ça. C'est une analyse de position. Cela pourrait être coûteux en termes de ressources, à la fois (mem et proc). – zanlok

1

Le problème peut-il être résolu à l'aide d'un dictionnaire afin que les éléments aient une relation qui ne soit pas du tout liée à l'ordre de tri?

2

Voici mon implémentation du comparateur (utilise LINQ, mais peut être facilement adapté aux anciennes versions .net). Vous pouvez l'utiliser pour tous les algorithmes de tri tels que Array.Sort, Enumerable.OrderBy, List.Sort, etc.

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

Le résultat est 2,1,3,4,5, - tous les éléments qui ne figurent pas dans le customOrder sont placés à la fin de la valeur par défaut pour le type donné (à moins qu'un comparateur de secours est donnée)

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 
} 
+0

Upboat pour (uint) IndexOf() de comparaison. – repka

Questions connexes