【问题标题】:Sorting List<FileInfo> in Natural sorted order .按自然排序顺序排序 List<FileInfo> 。
【发布时间】:2015-07-21 11:51:19
【问题描述】:

我有一个从 WCF 服务返回的列表,用于服务器上的文件列表。 后来我用它来填充我的客户端应用程序中的 TreeView

我需要列表按自然排序。

例如: 我有一个类似 List-1 的列表,我的预期结果是 List-2 但我得到List-3 作为我的输出。(参考下面给出的列表)

List-1          List-2          List-3
abc.jpg         abc.jpg         abc.jpg
abc10.jpg       abc10.jpg       abc10.jpg
abc100.jpg      abc97.jpg       abc100.jpg
abc98.jpg       abc98.jpg       abc101.jpg
abc97.jpg       abc100.jpg      abc102.jpg
abc102.jpg      abc101.jpg      abc97.jpg
abc101.jpg      abc102.jpg      abc98.jpg

到目前为止,我已经查看了 * 的帖子:

[1]:C# Sort files by natural number ordering in the name?[2]:Sorting a FileInfo[] based using Natural Sorting on the filename (SQL files).

他们都没有为我的案子工作,任何帮助将不胜感激:)

【问题讨论】:

  • 您的文件名是否总是包含非数字字符,然后是可选数字?
  • 不,它可能是任何东西......我们如何在任何文件系统中给出文件名

标签: c# list fileinfo


【解决方案1】:

给你;一个方便的自然排序列表扩展:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Demo
{
    // A List extension class for natural sorting.

    public static class ListExt
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        private static extern int StrCmpLogicalW(string lhs, string rhs);

        // Version for lists of any type.
        public static void SortNatural<T>(this List<T> self, Func<T, string> stringSelector)
        {
            self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs)));
        }

        // Simpler version for List<string>
        public static void SortNatural(this List<string> self)
        {
            self.Sort(StrCmpLogicalW);
        }
    }

    // Demonstrate using the List extension.

    public class Program
    {
        private static void Main(string[] args)
        {
            var names = new List<FileInfo>
            {
                new FileInfo("abc.jpg"),
                new FileInfo("abc10.jpg"),
                new FileInfo("abc100.jpg"),
                new FileInfo("abc98.jpg"),
                new FileInfo("abc97.jpg"),
                new FileInfo("abc102.jpg"),
                new FileInfo("abc101.jpg")
            };

            names.SortNatural(x => x.Name);

            foreach (var name in names)
                Console.WriteLine(name);
        }
    }
}

这个程序的输出是:

abc.jpg
abc10.jpg
abc97.jpg
abc98.jpg
abc100.jpg
abc101.jpg
abc102.jpg

这利用了 Windows API StrCmpLogicalW() 方法,该方法进行自然排序顺序比较,并使用 P/Invoke 调用它。

【讨论】:

  • 对不起 Watson,但我不想这样做,因为它已经是一个很大的应用程序,为一个简单的任务添加 Dll 还不够好,它们也应该是一些更简单的方法。
  • @MakIndia 您没有添加 DLL;该 DLL 已经是 Windows API 的一部分,并且已经安装在所有版本的 Windows 上。我严重怀疑你会找到比这更简单的方法(实际上只使用一行代码来声明 P/Invoke 和一行来调用它......)
  • 只是澄清我的疑虑:我的意思是在所有版本的 Windows 7,8 中它会一直存在吗,它的访问权限呢,如果系统的访问权限有限,它仍然可以正常工作吗? .
  • @MakIndia 是的,它会正常工作。它是自 Windows 98 以来一直存在的 Windows API 的基本部分。它极不可能从任何未来版本的 Windows 中删除;这会破坏很多应用程序!
  • @csharpcoder 为此,您必须使用SortedDictionary,以及使用StrCmpLogicalW() 实现的自定义IComparer&lt;string&gt;。这并非完全无关紧要,而且是一个不同的问题,因此您应该为此提出一个新问题。