【问题标题】:How to sort a two dimensional array by smallest number?如何按最小数字对二维数组进行排序?
【发布时间】:2020-09-26 15:32:24
【问题描述】:

我正在制作一个程序来计算文件夹中有多少行代码,您可以在其中输入要检查的扩展名(例如.cs),它会列出所有具有该扩展名的文件及其行代码如下:

1. BackgroundProcesses.cs: 153
2. App.xaml.cs: 15
3. MainTableManifest.cs: 41

目前,我只是使用Directory.GetFiles() 来获取文件,它们没有任何特定的顺序。但是,我想按每个文件的显示行数从最小到最大对每个文件进行排序,以便通过如下输出轻松查看最大的文件:

1. App.xaml.cs: 15
2. MainTableManifest.cs: 41
3. BackgroundProcesses.cs: 153

这是我的二维锯齿数组的基本样子:

string[][] arr = new string[][] {
    new string[]{"file1", "324"},
    new string[]{"file2", "1903"},
    new string[]{"file3", "617"}
};

显然,我需要在排序时将字符串转换为数字(我认为您不能拥有具有不同数组类型的锯齿状数组)。关于如何将锯齿状数组转换为类似的东西的任何想法?

string[][] arr = new string[][] {
    new string[]{"file1", "324"},
    new string[]{"file2", "617"},
    new string[]{"file3", "1903"}
};

【问题讨论】:

  • 不要使用二维字符串数组。使用类型化对象的集合(可能是List<>)。具有两个属性的类型,Name(字符串)和LineCount(整数)。你的程序会变得更简单
  • 看看@rossgurbutt 的回答。实现它,看看你是否能理解它。这是针对您的问题的经典面向对象的解决方案。在查看其他基于 tuple 的解决方案之前,您应该很好地掌握这一点。您可以尝试将这两种方法结合起来;从对象开始,然后使用 LINQ 排序并获取您的最终答案
  • 你可以使用值元组或字典来代替二维数组
  • 请使用 EnumerateFiles 而不是 GetFiles,尤其是在您的目录可能包含大量文件的情况下。稍后您会感谢自己,特别是如果您使用建议的将信息存储在强类型集合中的解决方案(甚至是值元组方法),您无论如何都会从 GetFiles 中丢弃数组

标签: c# arrays sorting multidimensional-array jagged-arrays


【解决方案1】:

你应该使用 ValueTuple 而不是 Jagged Arrays。

(string Filename, int Lines)[] files = ...

之后就可以使用 Linq 进行排序了

var sorted = files
    .OrderBy(item => item.Lines)
    .ThenBy(item => item.Filename);

【讨论】:

    【解决方案2】:

    面向对象的编程语言(如 C#)的主要特点之一是允许您定义自定义对象并具有与其相关的行为,而不是复杂的原生类型结构。

    您是否尝试过创建一个自定义对象来表示这些数据,然后可以进行相应的排序?
    例如

    public class FileRecord
    {
        public string FileName { get; }
        public int NumberOfLines { get; }
    
        public FileRecord(string fileName, int numberOfLines)
        {
            this.FileName = fileName;
            this.NumberOfLines = numberOfLines;
        }
    }
    

    然后您可以让这个类实现 IComparable 或为排序定义一个自定义比较器。我的偏好是使用自定义比较器,因为您可能希望在其他地方使用不同的标准和相同的类进行排序。

    这看起来像:

    public class FileRecordComparer : IComparer<FileRecord>
    {
        public int Compare(FileRecord x, FileRecord y)
        {
            // Could handle nulls here if you're expecting nulls
    
            int lineCompare = x.NumberOfLines.CompareTo(y.NumberOfLines);
    
            if (lineCompare == 0)
                return x.FileName.CompareTo(y.FileName);
            else
                return lineCompare;
        }
    }
    

    然后您可以使用以下代码对数组进行排序(当然,您必须以当前的方式填充它)

            // Could use a list here if you don't know the number of files
            FileRecord[] records = new FileRecord[numberOfFiles];
            // ...
            // Populate the records as you do currently, but creating instances of FileRecord
            // ...
            Array.Sort(records, new FileRecordComparer());
    

    【讨论】:

    • 这应该处理行数相等的情况。例如,然后按文件名排序。否则无法进行稳定的排序
    【解决方案3】:

    试试

    var files = arr.OrderBy(x =>Convert.ToInt64(x[1]));
    

    【讨论】:

    • 我应该看什么具体的东西?
    【解决方案4】:

    您可以使用 Tuple 和 Linq 来简化您的问题,同时获取文件和行数:

    (string Filename, int numberLines)[] files = Directory.GetFiles(@"d:\", "*.cs")
                                                          .Select(f => (f, File.ReadLines(f).Count()))
                                                          .OrderBy(f => f.Item2).ToArray();
    
            foreach (var file in files)
            {
                Console.WriteLine($"file:{file.Filename} lines:{file.numberLines}");
            }
    

    如果您的目录中有很多文件,我建议您使用 EnumerateFiles 而不是 GetFiles。

    【讨论】:

      猜你喜欢
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-31
      • 1970-01-01
      • 1970-01-01
      • 2023-01-02
      • 2018-06-02
      相关资源
      最近更新 更多