简体   繁体   English

如何在C#中对2D数组进行排序

[英]How to Sort 2D Array in C#

I've read lots of posts about sorting a 2D array but I still can't master it so I was wondering if anyone can offer me some advice... 我已经阅读了很多关于排序2D数组的帖子,但我仍然无法掌握它,所以我想知道是否有人可以给我一些建议......

I have an aray which lists letters and quantity (I'm doing a frequency anaysis on a piece of text). 我有一个列出字母和数量的aray(我正在对一段文字进行频率分析)。 I've read this data into a rectangle array and need to order it by highest frequency first. 我已将这些数据读入矩形数组,需要先按最高频率对其进行排序。 Here's my code so far: 到目前为止,这是我的代码:

    //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++;
    }

You are using a 2D array to represent 2 separate vectors - the symbols and the counts. 您正在使用2D数组来表示2个单独的向量 - 符号和计数。 Instead, use 2 separate arrays. 相反,使用2个单独的数组。 Array.Sort has an overload that takes 2 arrays, and sorts on one array, but applies the changes to both , achieving what you want. Array.Sort有一个重载,需要2个数组,并在一个数组上排序,但将更改应用于两者 ,实现你想要的。

This would also allow you to use a char[] for the characters rather than int[]: 这也允许你对字符而不是int []使用char []:

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

At this point, the counts have been ordered, and the symbols will still match index-by-index with the count they relate to. 此时,计数已经被排序,并且符号仍然将索引与它们相关的计数匹配。

You can wrap letter-count pair in a struct and use linq methods to manipulate data: 您可以在结构中包含字母数对,并使用linq方法来处理数据:

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

Sorting by count will look like this: 按计数排序将如下所示:

List<LetterCount> counts = new List<LetterCount>();
//filling the counts
counts = counts.OrderBy(lc => lc.Count).ToList();
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++;
        }
    }
}

In this case I'd choose to make use of KeyValuePair<TKey, TValue> and instead use something like this: 在这种情况下,我会选择使用KeyValuePair<TKey, TValue> ,而是使用以下内容:

//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++;
}

Then use Array.Sort : 然后使用Array.Sort

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

Alternative approach: 替代方法:

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

(untested) (另)

This'll sort a two dimension array, the bool specifies if it's sorted on the second dimension, but default it sorts on the first dimension. 这将对二维数组进行排序,bool指定它是否在第二维上排序,但默认情况下它在第一维上排序。

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

Why are you storing the character? 你为什么要存放角色? You can infer it from the array index and do not need to store it! 您可以从数组索引推断它,而不需要存储它! Use a one-dimensional array instead. 请改用一维数组。

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

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

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