C# 如何使用LINQ使用条件按子字符串对文件名进行排序?
我在一个文件夹及其子文件夹中有一些Excel(.xlsx)文件,我正试图在我的网站上列出这些文件。文件名的格式如下:C# 如何使用LINQ使用条件按子字符串对文件名进行排序?,c#,.net,linq,lambda,linq-to-sql,C#,.net,Linq,Lambda,Linq To Sql,我在一个文件夹及其子文件夹中有一些Excel(.xlsx)文件,我正试图在我的网站上列出这些文件。文件名的格式如下: 2018_MyData_Day.xlsx 2018_MyData_Month.xlsx 2018_MyData_Year.xlsx 2019_MyData_Day.xlsx 2019_MyData_Month.xlsx 2019_MyData_Year.xlsx 注:日、月和年是文本,不是实际数字日、月或年的占位符(以防误导) 我需要以降序文件名显示这些文件名,但要按特定顺序按
2018_MyData_Day.xlsx
2018_MyData_Month.xlsx
2018_MyData_Year.xlsx
2019_MyData_Day.xlsx
2019_MyData_Month.xlsx
2019_MyData_Year.xlsx
注:日
、月
和年
是文本,不是实际数字日、月或年的占位符(以防误导)
我需要以降序文件名显示这些文件名,但要按特定顺序按年
、日
或月
分组。因此,使用上面的列表,输出应该是:
2019_MyData_Year.xlsx
2018_MyData_Year.xlsx
2019_MyData_Day.xlsx
2018_MyData_Day.xlsx
2019_MyData_Month.xlsx
2018_MyData_Month.xlsx
我使用以下方法按年份和天
,月
,年
子字符串对文件名进行排序,但子字符串的顺序不正确:
var fileGroup = (
from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories)
let fileName = Path.GetFileName(file)
orderby fileName descending
select fileName
).OrderBy(f => f.Substring(f.LastIndexOf("_")))
我确定我需要一个条件,因为所需的顺序是定制的,但我不确定如何实现它
这是可能的还是有更好的方法来实现我想要的输出
谢谢 为什么不在将文件名投影到两个属性的位置使用选择按钮:
- 文件年份:2018年、2019年,直到第一个月
- FilePeriod:一个整数,其中(0)=年,(1)=天,(2)=月,第二个下划线后面的部分
我认为这可能会解决您的问题。您可以使用一些let轻松做到这一点:
var fileGroup = (from f in Directory.GetFiles(myPath, "201*.xlsx")
let fName = Path.GetFileNameWithoutExtension(f)
let ymd = fName.Substring("2000_MyData_".Length).ToLower()
let fOrder = (ymd == "year" ? 0 : ymd == "day" ? 1 : 2)
select new {f, year=int.Parse(fName.Substring(0,4)), o=fOrder})
.OrderBy(g => g.o)
.ThenByDescending(g => g.year)
.Select(g => g.f);
IEnumerable files=Directory.EnumerateFiles(myPath,searchPattern:*.xlsx”,searchOption:searchOption.AllDirectories)。选择(x=>Path.GetFileName(x));
Regex reg=新的Regex(“.*Day | Month | Year)\\\.xlsx”);
var groups=files.GroupBy(x=>reg.Match(x).groups[“dmy”].Value);
StringBuilder=新的StringBuilder();
foreach(组中的变量g.OrderBy(x=>x.Key==“年”?0:x.Key==“日”?1:2))
{
AppendLine();
foreach(g.OrderByDescending中的变量f(x=>x))
{
建筑商附录(f);
}
}
您可以按如下方式使用LINQ
var list = new []{
"2018_MyData_Day.xlsx",
"2018_MyData_Month.xlsx",
"2018_MyData_Year.xlsx",
"2019_MyData_Day.xlsx",
"2019_MyData_Month.xlsx",
"2019_MyData_Year.xlsx"
};
var result = list.GroupBy(x=> new { Type= x.Split(new[]{"_"},StringSplitOptions.RemoveEmptyEntries)[2]})
.Select(x=> new {Key = x.Key, FullName = x.OrderBy(c => c)});
您可以尝试将代码更改为:
var fileGroup = (
from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories)
let fileName = Path.GetFileName(file)
let fileParts = fileName.Split('.')[0].Split('_')
orderby fileParts[2] descending, fileParts[0] descending
select fileName
)
首先,你应该像你在讨论中写的那样对你的“字符串”进行分组,你的代码没有对你的收藏进行分组。所以_year、_month和_day是文件名中固定的后缀(我不确定我是否正确)?如果是这样的话,你可以将文件分成三个列表,并对它们进行排序==>filelist.Where(i=>i.EndsWith(“\u year”).OrderByDescending(i=>i);@MichałK.-我想这就是我遇到的问题。我不知道如何按照特定的顺序对
年
、日
和月
进行分组。@Martin是固定的文本后缀。文件名与问题中显示的完全相同,而不是类似“2019_MyData_2012.xlsx”的名称。根据您的建议,我必须写三个单独的语句,对吗?如果可能的话,我希望在一个语句中这样做。@user2063351查看我的答案:)
IEnumerable<string> files = Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories).Select(x => Path.GetFileName(x));
Regex reg = new Regex(".*_(?<dmy>Day|Month|Year)\\.xlsx");
var groups = files.GroupBy(x => reg.Match(x).Groups["dmy"].Value);
StringBuilder builder = new StringBuilder();
foreach (var g in groups.OrderBy(x => x.Key == "Year" ? 0 : x.Key == "Day" ? 1 : 2))
{
builder.AppendLine();
foreach(var f in g.OrderByDescending(x => x))
{
builder.AppendLine(f);
}
}
var list = new []{
"2018_MyData_Day.xlsx",
"2018_MyData_Month.xlsx",
"2018_MyData_Year.xlsx",
"2019_MyData_Day.xlsx",
"2019_MyData_Month.xlsx",
"2019_MyData_Year.xlsx"
};
var result = list.GroupBy(x=> new { Type= x.Split(new[]{"_"},StringSplitOptions.RemoveEmptyEntries)[2]})
.Select(x=> new {Key = x.Key, FullName = x.OrderBy(c => c)});
var fileGroup = (
from file in Directory.EnumerateFiles(myPath, searchPattern: "*.xlsx", searchOption: SearchOption.AllDirectories)
let fileName = Path.GetFileName(file)
let fileParts = fileName.Split('.')[0].Split('_')
orderby fileParts[2] descending, fileParts[0] descending
select fileName
)