如何在C#中对二维数组进行排序

3

我读了很多关于对2D数组进行排序的帖子,但我仍然无法掌握它,所以我想知道是否有人能给我一些建议...

我有一个列表字母和数量的数组(我正在对一段文本进行频率分析)。我已经将这些数据读入矩形数组中,并需要按最高频率的顺序进行排序。以下是我的代码:

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

你正在使用最新版本的C#吗? - Matt Cashatt
是的,我正在使用VS 2010。 - L1am22
你能举个例子(可能更小)来说明一个已排序的二维数组是什么样子吗?你是指分别对每一行进行排序,例如? - Marc Gravell
看起来你得到了一些很好的反馈,所以我会退出。我问了C#问题,以确保您可以利用Linq Lambda表达式。 - Matt Cashatt
该数组将包含两列 - 一列为字符,另一列为该字符的频率。因此,它存储了26个不同字母及其相关频率的概述。 - L1am22
抱歉 - 关于您的排序问题,我想对频率列进行排序,并将其与相关字母一起排序。int [26,2] letterFrequency = {66, 17}等......请注意,我将字母存储为其ASCII代码。 - L1am22
7个回答

17

您正在使用一个二维数组来表示两个不同的向量 - 符号和计数。相反,使用两个独立的数组。Array.Sort有一个重载版本,接受2个数组,并对其中一个数组进行排序,但将更改应用于两个数组,从而实现您想要的效果。

这还允许您使用char[]来代替int[]来存储字符:

char[] symbols = ...
int[] counts = ...
...load the data...
Array.Sort(counts, symbols);
// all done!
在这一点上,计数已被排序,符号仍将与它们相关的计数按索引一一匹配。

4

您可以将字母计数对包装在结构体中,并使用linq方法来操作数据:

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

按计数排序的结果如下:
List<LetterCount> counts = new List<LetterCount>();
//filling the counts
counts = counts.OrderBy(lc => lc.Count).ToList();

这与使用通用的 KeyValuePair<TKey, TValue> 相同,只不过你可以给它命名。 - Aidiakapi
是的,但命名可以使代码更易读,现在创建一个结构体可以为将来的新逻辑做好准备。 - Dmitry Polyanitsa
我认为这只会使代码变得混乱,但这只是我的观点。就像C++中的typedefs一样。如果你有无数个类型都指向同一类型,那么这只会让事情更加混乱。再次强调,这只是我的观点。 - Aidiakapi
在这种情况下,这是一个品味问题,我同意。 - Dmitry Polyanitsa

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

0
在这种情况下,我会选择使用 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++;
}

然后使用 Array.Sort

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

0

另一种方法:

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

(未经测试)


最好使用SortedDictionary<TKey, TValue>。但是你的另一个解决方案是最好的 :P。 - Aidiakapi
@Aidiakapi 不是的;那是按键排序,我们想要按值排序。 - Marc Gravell
抱歉,我想说的是 SortedList<TKey, TValue> ;) - Aidiakapi

0
这段代码可以对一个二维数组进行排序,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];
    }
}

0
为什么要存储字符?你可以从数组索引中推断出它,不需要存储它!使用一维数组即可。
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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接