根据名称C#中可变长度的数字对文件进行排序

时间:2018-06-05 09:34:45

标签: linq sorting blender

我正在为Monitor Blender渲染项目编写一个程序。 但我有一个排序搅拌机输出的问题(一个3d程序)。 它以nummeric格式生成文件。或者在某些文本中以数字格式结束。

这里的问题是它的数字如下:
someprojectname-0001.png
someprojectname-0010.png
someprojectname-10104.png
someprojectname-10105.png
someprojectname-9999.png

在数字之前可能有一些文字,但问题接缝到目前为止我尝试的任何排序,看到9999高于10104(一些问题是额外的数字,并且数字的数字也没有固定。

应该输出
someprojectname-0001.png
someprojectname-0010.png
someprojectname-9999.png
someprojectname-10104.png

基本上连接所有数字(忽略任何文本),然后按编号排序,所以我尝试了:

d = new DirectoryInfo(renderpath);

//  FileInfo[] files = d.GetFiles( rendertpye).OrderBy(p => p.Name).ToArray();

FileInfo[] files = d.GetFiles(rendertpye).OrderByDescending(o => string.IsNullOrEmpty(o.Name)).ThenBy(o =>
            {
                int result;
                if (Int32.TryParse(o.Name, out result))
                { return result; }
                else
                { return Int32.MaxValue; }
            }).ToArray();

我还尝试过Numeric beforeAlpha sort(https://www.codeproject.com/Tips/543502/Numeric-before-alpha-sort-in-LINQ) 我试过(https://www.dotnetperls.com/alphanumeric-sorting)。

问题虽然他们都无法处理搅拌器文件编号的非固定数字长度。

更新 我的目标不是规定人们如何保存他们的BlendFiles,程序需要一个数组来检索所有保存的文件,并根据文件名中的数字排序,可以是可变数字大小。

我用linq尝试过,但我开始怀疑它可以直接用Linq完成。 也许虽然如果我们根据文件名创建一个int列表,然后命令该列表并使用该列表来命令名为list的原始文本..

1 个答案:

答案 0 :(得分:0)

解决了它,创建了一个结构(对于这个不太理想),我在其上为每个fileinfo条目添加了一个int计数器。一些正则表达式从文件名中擦除文本,该函数保留原始名称和fileInfo,但返回它们按照它们包含的数字排序。

未来的扩展可能也是对最后修改的属性进行排序 这可能会更容易。稍微改进可能只是在名称末尾找到数字,因为project2-frame33.blend会出现问题。 可能一些聪明的正则表达式可以做到这一点。

struct numericfile
    {
        public int filenr; public FileInfo file;
    }
public List<FileInfo> SortedbyNumber(List<FileInfo> files)
    {
        List<numericfile> filesnrs = new List<numericfile>();
        foreach (FileInfo file in files)
        {
            numericfile nf = new numericfile();
            nf.filenr = Convert.ToInt32(Regex.Replace(file.Name, "[^0-9]+", string.Empty));
            nf.file = file;
            filesnrs.Add(nf);
        }
        filesnrs.Sort((s1, s2) => s1.filenr.CompareTo(s2.filenr));
        files.Clear();
        foreach (numericfile fnr in filesnrs)
        {
            files.Add(fnr.file);
        }
        return files;
    }