2012-01-14 5 views
3

J'ai lu beaucoup de messages sur le tri d'un tableau 2D mais je ne peux toujours pas maîtriser je me demandais si si quelqu'un peut me donner quelques conseils ...Comment trier un tableau 2D en C#

Je un tableau qui liste les lettres et la quantité (je fais une analyse de fréquence sur un morceau de texte). J'ai lu ces données dans un tableau rectangle et j'ai besoin de le commander par la fréquence la plus élevée en premier. Voici mon code jusqu'à présent:

//create 2D array to contain ascii code and quantities 
    int[,] letterFrequency = new int[26, 2]; 

    //fill in 2D array with ascaii code and quantities 
    while (asciiNo <= 90) 
    { 

     while ((encryptedText.Length - 1) > counter) 
     { 
       if (asciiNo == (int)encryptedText[index]) 
       { 
         letterCount++; 
       } 
       counter++; 
       index++; 
     } 

    letterFrequency[(storeCount), (0)] = (char)(storeCount+66); 
    letterFrequency[(storeCount), (1)] = letterCount; 
    storeCount++; 
    counter=0; 
    index=0; 
    letterCount = 0; 
    asciiNo++; 
    } 
+0

Utilisez-vous la dernière version de C#? –

+0

Ouais, j'utilise VS 2010? – L1am22

+0

Pouvez-vous donner un exemple (peut-être plus petit) de ce à quoi ressemble un tableau 2D trié? Voulez-vous dire trier chaque rangée séparément, par exemple? –

Répondre

12

Vous utilisez un tableau 2D pour représenter 2 vecteurs distincts - les symboles et les comptes. Au lieu de cela, utilisez 2 tableaux séparés. Array.Sort a une surcharge qui prend 2 baies, et trie un tableau, mais applique les changements à tous les deux, en réalisant ce que vous voulez.

Cela vous permettra également d'utiliser un char [] pour les personnages plutôt que int []:

char[] symbols = ... 
int[] counts = ... 
...load the data... 
Array.Sort(counts, symbols); 
// all done! 

À ce stade , les comptes ont été commandés, et les symboles seront toujours correspondre indicielle par-index avec le nombre auquel ils se rapportent.

+0

Fantastique, merci beaucoup Marc. – L1am22

+0

Grande solution :) – Aidiakapi

+0

Brillant beaucoup plus élégant que l'un des autres travaux autour de là-bas. – chris

0

Dans ce cas, je choisirais d'utiliser KeyValuePair<TKey, TValue> et au lieu d'utiliser quelque chose comme ceci:

//create 2D array to contain ascii code and quantities 
KeyValuePair<char, int>[] letterFrequency = new KeyValuePair<char, int>[26]; 

//fill in 2D array with ascaii code and quantities 
while (asciiNo <= 90) 
{ 

    while ((encryptedText.Length - 1) > counter) 
    { 
      if (asciiNo == (int)encryptedText[index]) 
      { 
        letterCount++; 
      } 
      counter++; 
      index++; 
    } 

letterFrequency[storeCount] = new KeyValuePair<char, int>((char)(storeCount+66), letterCount); 
storeCount++; 
counter=0; 
index=0; 
letterCount = 0; 
asciiNo++; 
} 

Ensuite, utilisez Array.Sort:

Array.Sort(letterFrequency, (i1, i2) => i2.Value.CompareTo(i1.Value)); 
0

approche alternative:

var counts = new Dictionary<char,int>(); 
foreach(char c in text) { 
    int count; 
    counts.TryGetValue(c, out count); 
    counts[c] = count + 1; 
} 
var sorted = counts.OrderByDescending(kvp => kvp.Value).ToArray(); 
foreach(var pair in sorted) { 
    Console.WriteLine("{0}: {1}", pair.Key, pair.Value); 
} 

(non testé)

+0

Mieux vaut utiliser un 'SortedDictionary ' alors. Mais votre autre solution est la meilleure: P. – Aidiakapi

+0

@Aidiakapi no; qui trie sur la clé; nous voulons trier sur la valeur –

+0

Désolé, je voulais dire 'SortedList ';) – Aidiakapi

2

Vous pouvez envelopper paire nombre de lettres dans une struct et utiliser des méthodes de LINQ pour manipuler des données:

struct LetterCount { 
    public char Letter { get; set; } 
    public int Count { get; set; } 
} 

Tri par nombre ressemblera à ceci:

List<LetterCount> counts = new List<LetterCount>(); 
//filling the counts 
counts = counts.OrderBy(lc => lc.Count).ToList(); 
+0

C'est la même chose que d'utiliser le générique 'KeyValuePair ', sauf que vous obtenez de le nommer. – Aidiakapi

+0

Oui, mais le nommage donne plus de lisibilité et faire une structure peut maintenant préparer le code pour la nouvelle logique dans le futur. –

+0

Imo ça encombre le code, mais comme je dis c'est mon avis. Tout comme C++ avec ses typedefs. Si vous avez un zillion, tous les types se réfèrent au même type. Ensuite, cela devient confus. Encore une fois, mon opinion. – Aidiakapi

0

Ça va trier un tableau à deux dimensions , le booléen spécifie s'il est trié sur la deuxième dimension, mais par défaut il trie sur la première dimension.

void SortDoubleDimension<T>(T[,] array, bool bySecond = false) 
{ 
    int length = array.GetLength(0); 
    T[] dim1 = new T[length]; 
    T[] dim2 = new T[length]; 
    for (int i = 0; i < length; i++) 
    { 
     dim1[i] = array[i, 0]; 
     dim2[i] = array[i, 1]; 
    } 
    if (bySecond) Array.Sort(dim2, dim1); 
    else Array.Sort(dim1, dim2); 
    for (int i = 0; i < length; i++) 
    { 
     array[i, 0] = dim1[i]; 
     array[i, 1] = dim2[i]; 
    } 
} 
0

Pourquoi gardez-vous le personnage? Vous pouvez déduire à partir de l'index de tableau et n'avez pas besoin de le stocker! Utilisez un tableau unidimensionnel à la place.

string encryptedText = "Test".ToUpper(); 
int[] frequency = new int[26]; 
foreach (char ch in encryptedText) { 
    int charCode = ch - 'A'; 
    frequency[charCode]++; 
} 
var query = frequency 
    .Select((count, index) => new { Letter = (char)(index + 'A'), Count = count }) 
    .Where(f => f.Count != 0) 
    .OrderByDescending(f => f.Count) 
    .ThenBy(f => f.Letter); 
foreach (var f in query) { 
    Console.WriteLine("Frequency of {0} is {1}", f.Letter, f.Count); 
} 
1
public static void Sort2DArray<T>(T[,] matrix) 
{ 
    var numb = new T[matrix.GetLength(0) * matrix.GetLength(1)]; 

    int i = 0; 
    foreach (var n in matrix) 
    { 
     numb[i] = n; 
     i++; 
    } 
    Array.Sort(numb); 

    int k = 0; 
    for (i = 0; i < matrix.GetLength(0); i++) 
    { 
     for (int j = 0; j < matrix.GetLength(1); j++) 
     { 
      matrix[i, j] = numb[k]; 
      k++; 
     } 
    } 
}