C# 对目录中的文件名进行排序,结果排序错误

C# 对目录中的文件名进行排序,结果排序错误,c#,linq,directory,C#,Linq,Directory,我在目录中有文件,文件名如下: 批次1.10.18.xlsx 批次2.10.18.xlsx … 批次31.10.18.xlsx 如您所见,它们具有以下模式:批处理dd.mm.yy.xlsx 我需要按照文件名中日期的顺序处理它们 到目前为止的代码: private void processFiles(string BatchFilePath) { IOrderedEnumerable<string> fileEntries = Directo

我在目录中有文件,文件名如下:

批次1.10.18.xlsx
批次2.10.18.xlsx

批次31.10.18.xlsx

如您所见,它们具有以下模式:批处理
dd.mm.yy.xlsx

我需要按照文件名中日期的顺序处理它们

到目前为止的代码:

private void processFiles(string BatchFilePath)
{
     IOrderedEnumerable<string> fileEntries = 
                Directory.GetFiles(BatchFilePath, "Batch *.xlsx")
                .OrderBy(f => GetFileDay(f));

     foreach (string fileName in fileEntries)
     {
        Console.WriteLine("Processing File " + Path.GetFileName(fileName));

        // Code that read and process files 
     }

}

private int GetFileDay(string file)
{
    string s1=  file.Substring(7, 2);
    if (s1.Substring(1) == ".")
        s1 = s1.Substring(0, 1);
     return int.Parse(s1);
}
private void processFiles(字符串BatchFilePath)
{
IOrderedEnumerable文件项=
Directory.GetFiles(BatchFilePath,“Batch*.xlsx”)
.OrderBy(f=>GetFileDay(f));
foreach(文件项中的字符串文件名)
{
Console.WriteLine(“处理文件”+Path.GetFileName(fileName));
//读取和处理文件的代码
}
}
私有int GetFileDay(字符串文件)
{
字符串s1=file.Substring(7,2);
if(s1.子串(1)=“)
s1=s1.子串(0,1);
返回int.Parse(s1);
}
代码不起作用。它仍然以错误的顺序给我文件名,如下所示:

批次25.10.18.xlsx
批次22.10.18.xlsx…
批次9.10.18.xlsx
批次3.10.18.xlsx

将字符串(如“1.10.18”)解析为真实的
日期时间(2018-10-01):


考虑到您的文件集合将是
IEnumerable
,这将按照区域性的实际日期[而不是字符串!]进行排序

var l  = new List<string>()
{
   "c:\\dev\\Batch 1.10.18.xlsx", 
   "c:\\dev\\Batch 2.10.18.xlsx", 
   "c:\\dev\\Batch 31.10.18.xlsx"
};

var ci = CultureInfo.GetCultureInfo("fr-FR"); // pick culture is same as pick format. You need to pre-define one
var r = l.Select(x=>new{name = x, parts = Path.GetFileNameWithoutExtension(x).Split(" .".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)}).
        Select(a=> new {name = a.name, date = DateTime.Parse(a.parts[1] + "/" + a.parts[2] + "/" + a.parts[3], ci)}).
        OrderBy(x => x.date); //OrderByDescending(x => x.date);

r.ToList().ForEach(x => Console.WriteLine(x.name));
var l=新列表()
{
“c:\\dev\\Batch 1.10.18.xlsx”,
“c:\\dev\\Batch 2.10.18.xlsx”,
“c:\\dev\\Batch 31.10.18.xlsx”
};
var ci=CultureInfo.GetCultureInfo(“fr”);//拾取区域性与拾取格式相同。您需要预先定义一个
var r=l.Select(x=>new{name=x,parts=Path.getfilename withoutextension(x).Split(“.”.tocharray(),StringSplitOptions.removemptyentries)})。
选择(a=>new{name=a.name,date=DateTime.Parse(a.parts[1]+“/”+a.parts[2]+“/”+a.parts[3],ci)})。
OrderBy(x=>x.date)//OrderByDescending(x=>x.date);
r、 ToList().ForEach(x=>Console.WriteLine(x.name));
输出

批次1.10.18.xlsx
批次2.10.18.xlsx
批次31.10.18.xlsx


这可以更有效地完成,但线性度较低。

您可以使用以下正则表达式。然后您可以在Linq上执行OrderBy/OrderByDescending操作:

Regex r = new Regex(@"\d{1,2}.\d{1,2}.\d{2}");
var orderByDateList = items.Where(po => r.IsMatch(po)).OrderByDescending(po => DateTime.ParseExact(r.Match(po).Value, "d.M.yy", null)).ToList(); // lines that match date pattern

使用正则表达式从文件名解析日期,并根据日期时间排序。这是修改后的代码

public static IOrderedEnumerable<string> GetFiles(string batchFilePath)
        {
            if (Directory.Exists(batchFilePath))
            {
                var directoryInfo = new DirectoryInfo(batchFilePath);
                var fileEntries = directoryInfo.GetFiles(@"Batch *.xlsx").Select(x => x.Name).OrderBy(f => GetFileDay(f));
                return fileEntries;
            }

            return null;
        }

    private static DateTime GetFileDay(string file)
    {
        var date = default(DateTime);
        var extractedDate = Regex.Match(file, @"(\W\S*(\d[\d]{0,2}))").Value;
        extractedDate = extractedDate.Replace(".", "-").Trim();           
        DateTime.TryParseExact(extractedDate, "d-MM-yy", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out date);
        return date;
    }
公共静态IORDerenumerable GetFiles(字符串batchFilePath)
{
if(Directory.Exists(batchFilePath))
{
var directoryInfo=新的directoryInfo(batchFilePath);
var fileEntries=directoryInfo.GetFiles(@“Batch*.xlsx”)。选择(x=>x.Name)。OrderBy(f=>GetFileDay(f));
返回文件条目;
}
返回null;
}
私有静态日期时间GetFileDay(字符串文件)
{
变量日期=默认值(日期时间);
var extractedDate=Regex.Match(文件,@“(\W\S*(\d[\d]{0,2})))).Value;
extractedDate=extractedDate.Replace(“.”,“-”).Trim();
DateTime.TryParseExact(提取日期,“d-MM-yy”,CultureInfo.InvariantCulture,datetimestyle.AllowWhiteSpaces,过期);
返回日期;
}


向我们显示预期的订单v订单seen@John我想“看到”的顺序是“批次3.10.18”,然后是“批次31.10.18”,然后是“批次4.10.18”。我们可以假设您无法控制文件本身的命名吗?最好的答案可能还取决于文件的数量,这会阻止用户界面吗?谁知道排序这么有趣一些非常复杂的解决方案。我认为我的建议非常简单易懂——但这只是我自己的一个反映:-)我认为好的答案不应该只包含代码解决方案。您介意添加一些关于您的代码正在执行的内容和原因的信息吗?@vasily.sib已编辑。@skyoxZ谢谢,您还可以添加问题中的完整代码吗,这样每个人都可以看到您如何使用
GetFileDay
方法?这不是一个过度设计的解决方案吗?@vasily.sib按日期排序,而不是按日期的字符串表示。我可以使用1个select,但出于示例的考虑,编写时间会更长另一个答案也是按
DateTime
排序,但它不会为每个文件名实例化2个匿名对象,也不依赖于确切的区域性:\@vasily.sib另一个答案还使用2个字符串搜索\解析方法并处理单个文件。而我的示例展示了LINQ的功能。这里提供了格式,好吗。?如果每一个答案都是一样的,生活将是无聊的。我的答案是关于linq、日期区域性等,它不排序
var fileEntries=Directory.GetFiles(BatchFilePath,“Batch*.xlsx”).OrderBy(GetFileDay)-也是LINQ。它只是使用私有方法而不是lambda。我想你没有测试这个:)
d.M.yy
-
M
是几分钟,不是几个月。来吧,伙计们。已经有一个基于
DateTime.ParseExact()
的答案,为什么要添加另一个?为什么这不仅仅是一个注释(“嘿,你也可以使用
Regex
”)呢?我是否应该添加另一个答案,即调用一个HTTP请求到远程神经网络,它可以从字符串中提取日期?@vasily.sib好的,Vasya,你只是想控制每个人的想法、方法等。让我们选择他们喜欢的。让选民投票。各种各样的答案对OP来说都是好事,因为对于某些人来说,整个新世界可能只是opened@T.S.我当然不想控制任何人。我想要的是,SO将专注于改进现有答案,而不是复制粘贴现有答案。Gauravsa,如果我关于神经网络的示例看起来很粗糙,很抱歉,这只是我想到的第一个另一个示例。
public static IOrderedEnumerable<string> GetFiles(string batchFilePath)
        {
            if (Directory.Exists(batchFilePath))
            {
                var directoryInfo = new DirectoryInfo(batchFilePath);
                var fileEntries = directoryInfo.GetFiles(@"Batch *.xlsx").Select(x => x.Name).OrderBy(f => GetFileDay(f));
                return fileEntries;
            }

            return null;
        }

    private static DateTime GetFileDay(string file)
    {
        var date = default(DateTime);
        var extractedDate = Regex.Match(file, @"(\W\S*(\d[\d]{0,2}))").Value;
        extractedDate = extractedDate.Replace(".", "-").Trim();           
        DateTime.TryParseExact(extractedDate, "d-MM-yy", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out date);
        return date;
    }