在LINQ中对路径列表排序?
假设我有以下文件夹:在LINQ中对路径列表排序?,linq,sorting,path,hierarchy,flatten,Linq,Sorting,Path,Hierarchy,Flatten,假设我有以下文件夹: New Folder - New Folder - New Folder (2) - New Folder (3) - New Folder (4) New Folder (2) New Folder (3) New Folder (4) 还有一个问题 from s in Directory.GetDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories) select s 结果是: D:
New Folder
- New Folder
- New Folder (2)
- New Folder (3)
- New Folder (4)
New Folder (2)
New Folder (3)
New Folder (4)
还有一个问题
from s in Directory.GetDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories)
select s
结果是:
D:\Project\uploads\New Folder
D:\Project\uploads\New Folder (2)
D:\Project\uploads\New Folder (3)
D:\Project\uploads\New Folder (4)
D:\Project\uploads\New Folder\New Folder
D:\Project\uploads\New Folder\New Folder (2)
D:\Project\uploads\New Folder\New Folder (3)
D:\Project\uploads\New Folder\New Folder (4)
是否有方法将列表按正确顺序排序?我希望是:
D:\Project\uploads\New Folder
D:\Project\uploads\New Folder\New Folder
D:\Project\uploads\New Folder\New Folder (2)
D:\Project\uploads\New Folder\New Folder (3)
D:\Project\uploads\New Folder\New Folder (4)
D:\Project\uploads\New Folder (2)
D:\Project\uploads\New Folder (3)
D:\Project\uploads\New Folder (4)
任何帮助都将不胜感激 使用.NET4.0试试看
Directory.EnumerateDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories)
它可能会做你期望的事情。如果没有,您可以显式执行:
Directory.GetDirectories(@"D:\Project\uploads")
.SelectMany(dir => dir.GetDirectories().OrderBy(sub => sub.Name))
最后,您可以执行以下操作:
from s in Directory.GetDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories)
order by s.Parent.Name, s.Name
select s
from s in Directory.GetDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories)
let members = s.Name.Split(new [] {Path.SeparatorChar})
order by members[2], s.Name
select s
以获得更大的控制/灵活性。根据您的需要选择最简单的方法关于默认顺序,您唯一需要更改的是确保
\
字符始终被视为字母表中的第一个字母。我没有一个确切的答案如何实现这一点,但是:
- 如果找到一种方法将字符串中的
替换为小于所有其他字符的字符,并将替换后的字符串用作键,则可以使用\
子句order by
- 您可以使用
并实现重新实现字符串比较的字符串比较器,但对Array.Sort
字符的附加规则进行编码\
- 这并不像我想的那么琐碎。也许最明智的解决方案(除了递归地构建列表之外)是实现一个比较器来进行排序
谢谢你的评论和回答,伙计们 我想有了递归,生活会轻松得多
void Main()
{
string rootFolder = @"D:\Project\uploads";
string[] f = Directory.GetDirectories(rootFolder, "*.*", SearchOption.AllDirectories);
Func<string, string[]> build = null;
build = (p) => {
return (from x in f where Path.GetDirectoryName(x) == p
from y in new string[]{ x }.Union(build(x)) select y).ToArray();
};
f = build(rootFolder).Dump();
}
void Main()
{
string rootFolder=@“D:\Project\uploads”;
字符串[]f=Directory.GetDirectories(rootFolder,*.*,SearchOption.AllDirectories);
Func build=null;
构建=(p)=>{
返回(从f中的x开始,其中Path.GetDirectoryName(x)=p
从新字符串[]{x}.Union(build(x))中的y中选择y.ToArray();
};
f=构建(rootFolder.Dump();
}
嗯,我没想到那一个。GetDirectories()
是否保证按排序顺序返回目录?否则你必须对它进行排序。我认为第二个版本需要是递归的。@Tomas:我也可以这样想,但它在任何地方都不明确,让OP决定你也可以为此目的对你的区域设置cultureinfo进行黑客攻击。我建议你“说出你的意思”(有意编程)@NVA:是的,我刚刚注意到这个。。。不是我在某些输入上预期的顺序。让我看看是否可以调整它。@Byul:我发现了如何实现这样一个比较器。所以,如果你想通过排序来实现这一点,你可以使用这个比较器。p、 美国,名称变更?:)哦,伙计,我不知道使用顺序比较器会有什么不同,尽管在这里制作一个新的比较器并不是真的必要。是的。你是对的。x=>x.Replace(Path.directoryseportorchar,'\0')是使用StringComparer.Ordinal comparer的一个很好的键选择器
var query = Directory
.EnumerateDirectories(@"D:\Project\uploads", "*", SearchOption.AllDirectories)
.OrderBy(name => name.Replace(Path.DirectorySeparatorChar, '\0'), StringComparer.Ordinal);
void Main()
{
string rootFolder = @"D:\Project\uploads";
string[] f = Directory.GetDirectories(rootFolder, "*.*", SearchOption.AllDirectories);
Func<string, string[]> build = null;
build = (p) => {
return (from x in f where Path.GetDirectoryName(x) == p
from y in new string[]{ x }.Union(build(x)) select y).ToArray();
};
f = build(rootFolder).Dump();
}
private class Comparer : IComparer<string>
{
public int Compare(string x, string y)
{
return StringComparer.Ordinal.Compare(x.Replace(Path.DirectorySeparatorChar, '\0'),
y.Replace(Path.DirectorySeparatorChar, '\0'));
}
}
var source = Directory.GetDirectories(@"D:\Project\uploads", "*.*", SearchOption.AllDirectories)
var target = source.OrderBy(x => x, new Comparer()).ToArray();