【问题标题】:How to add files to a list after order by its name?如何按名称排序后将文件添加到列表中?
【发布时间】:2016-02-25 05:51:39
【问题描述】:

我选择文件夹中的所有文件并将所有文件名添加到 2 个列表中。 xmlFilePathlistVersion

例如,我的文件名如下所示

1.8.1

1.8.2

1.10.0

1.10.1

但以下代码添加其名称如下。

1.10.0, 1.10.1, 1.8.1, 1.8.2

我想改变它的顺序如下(按它的名字排序)

1.8.1, 1.8.2, 1.10.0, 1.10.1,

我怎样才能达到这个要求?

FolderBrowserDialog folderDlg = new FolderBrowserDialog();
DialogResult result = folderDlg.ShowDialog();

if (result == DialogResult.OK)
{
    string[] files = Directory.GetFiles(folderDlg.SelectedPath);
    lblFolder.Text = "Folder : " + folderDlg.SelectedPath;
    lblFiles.Text = "No of Xml Found : " + files.Length.ToString();

    try
    {
        foreach (string filePath in Directory.GetFiles(folderDlg.SelectedPath))
        {
            xmlFilePath.Add(filePath);
        }

        foreach (string file in files)
        {
            string fileName = Path.GetFileNameWithoutExtension(file);
            listVersion.Add(fileName);
        }
    }
    catch (System.Exception ex)
    {
        lbl_notifications.Text = ex.Message;
    }
}

【问题讨论】:

  • 这些数字看起来像语义版本号,使用 semver 订购可以查看this answer

标签: c# .net list sorting version


【解决方案1】:

问题在于它将名称排序为文​​本,而不考虑项目的数值。在文本中,“1”小于“8”,“1”后跟“0”无关紧要。

这样做:

string[] files = Directory.GetFiles(folderDlg.SelectedPath);
files = files.OrderBy(f => int.Parse(f.Split(".")[0]))
              .ThenBy(f => int.Parse(f.Split(".")[1]))
              .ThenBy(f => int.Parse(f.Split(".")[2])).ToArray();

您可以通过在开头创建一个包含文件名和拆分部分的.Select() 投影来进一步改进这一点,这样您就不必继续重新拆分()-ing 相同的字符串,但这应该至少工作。

【讨论】:

    【解决方案2】:

    如果文件名实际上是版本,则将它们按版本排序:

      string[] files = Directory.GetFiles(folderDlg.SelectedPath);
    
      Array.Sort(files, (left, right) => 
        new Version(Path.GetFileNameWithoutExtension(left)).CompareTo(
        new Version(Path.GetFileNameWithoutExtension(right))));
    

    编辑:一般情况,例如对于像 "v_1.2.4 bla-bla-bla 5.6.7" 这样的名称,您可以使用 StrCmpLogicalW 函数(就像 File Explorer 所做的那样)或其类似物

    using System.Runtime.InteropServices;
    
    ...
    
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int StrCmpLogicalW(string x, string y);
    ...
    
    string[] files = Directory.GetFiles(folderDlg.SelectedPath);
    
    Array.Sort(files, (left, right) => StrCmpLogicalW(
      Path.GetFileNameWithoutExtension(left),
      Path.GetFileNameWithoutExtension(right)));
    

    【讨论】:

    • 是的..这确实有效。如果我使用文件名作为“v_1.8.1”,它会给出一个名为“输入字符串格式不正确”的错误。对于那种文件名,我该如何使用这个解决方案?
    • @Sachith - 如果您的文件名以 "v_" 开头,那么您应该在问题中提到这一点。
    • @Sachith:一般情况下,我建议使用StrCmpLogicalW 函数(或其类似物)。查看我的编辑
    【解决方案3】:

    您似乎在处理表示版本的字符串。

    您可以将它们转换为版本并对其进行排序。

    var sortedVersions = files.Select(x => new Version(x)).OrderBy(x => x);
    

    现在您可以使用sortedVersions 或将其转换回字符串数组。

    files = sortedVersions.Select(x => x.ToString()).ToArray();
    

    您可以查看Version 类,如果它更合适就使用它。使用字符串是有风险的,您可以通过使用适当的数据类型来降低这种风险。

    如果文件名以“v_”开头,那么你可以修改上面的代码并处理它。

    var sortedVersions = files.Select(x => new Version(x.Substring(2))).OrderBy(x => x);
    files = sortedVersions.Select(x => "v_" + x.ToString()).ToArray();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-14
      • 2021-09-30
      • 2011-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      相关资源
      最近更新 更多