【问题标题】:Linq to get distinct subdirectories from list of pathsLinq 从路径列表中获取不同的子目录
【发布时间】:2014-05-30 12:32:31
【问题描述】:

我正在尝试在 C# 中为一个项目制作一个文件目录浏览器。

我从当前路径开始(对于这个例子,它将是'/')。

从我拥有的路径列表中

示例:/a/b、/a/bb、/a/bbb、/b/a、/b/aa、/b/aaa、/c/d、/d/e

我想返回一个不同子目录的列表

预期回报:/a/、/b/、/c/、/d/

如何使用 LINQ 来完成这项工作?

【问题讨论】:

  • 是什么让您认为应该使用 Linq?这是一个很棒的工具,但它不是解决所有问题的方法......
  • 在我真正尝试实现之前似乎最简单。你会推荐其他东西吗?
  • 不一定;我只是说,当你在寻找问题的解决方案时,你可能不应该使用特定的工具。
  • Directory.GetDirectories("path") 将列出您的所有子目录。并且由于文件和目录在其父目录中必须是唯一的,因此它将是一个不同的列表。
  • @ThomasLevesque 好吧,我有一个在 LINQ 中工作的解决方案,希望有人能想出一些不那么脆弱的东西。

标签: c# linq list distinct


【解决方案1】:

我认为这几乎涵盖了它。示例控制台应用程序:

public static void Main()
{
    string[] paths = new[] { "/a/b", "/a/bb", "/a/bbb", "/b/a", "/b/aa", "/b/aaa", "/c/d", "/d/e" }; 
    string root = "/";

    Console.WriteLine(string.Join(", ", paths.Select(s => GetSubdirectory(root, s)).Where(s => s != null).Distinct()));
}

static string GetSubdirectory(string root, string path)
{
    string subDirectory = null;
    int index = path.IndexOf(root);

    Console.WriteLine(index);
    if (root != path && index == 0)
    {
        subDirectory = path.Substring(root.Length, path.Length - root.Length).Trim('/').Split('/')[0];
    }

    return subDirectory;
}

见小提琴:http://dotnetfiddle.net/SXAqxY

示例输入:“/”
样本输出:a、b、c、d

示例输入:“/a”
样本输出:b, bb, bbb

【讨论】:

  • 很棒的答案。效果很好!
【解决方案2】:

我可能没有抓住重点,但这样的东西难道不是您要找的吗?

var startingPath = @"c:\";

var directoryInfo = new DirectoryInfo(startingPath);

var result = directoryInfo.GetDirectories().Select(x => x.FullName).ToArray();

结果将是一个指向各个直接子目录的路径数组(示例):

  1. "c:\Boot"
  2. "c:\Temp"

【讨论】:

  • 我没有对任何实际目录进行操作。它只是一个目录路径列表。
【解决方案3】:
void Main()
{
  string [] paths = {  @"/a/b", @"/a/bb", @"/a/bbb", @"/b/a", @"/b/aa", @"/b/aaa", @"/c/d", @"/d/e" };

  var result = paths.Select(x => x.Split('/')[1]).Distinct();

  result.Dump();
}

如果你不知道你是否有一个领先的/,那么使用这个:

var result = paths.Select(x =>x.Split(new string [] {"/"},
                                        StringSplitOptions.RemoveEmptyEntries)[0])
                  .Distinct();

【讨论】:

    【解决方案4】:

    你可以使用 Path.GetPathRoot

    var rootList = new List <string>();
    
    foreach (var fullPath in myPaths)
    {
        rootList.Add(Path.GetPathRoot(fullPath))
    }
    
    return rootList.Distinct();
    

    或者:

    myPaths.Select(x => Path.GetPathRoot(x)).Distinct();
    

    或者使用 Directory.GetDirectoryRoot:

    myPaths.Select(x => Directory.GetDirectoryRoot(x)).Distinct();
    

    编辑

    如果你想要 N+1 路径,你可以这样做:

    string dir = @"C:\Level1\Level2;  
    
    string root = Path.GetPathRoot(dir);
    
    string pathWithoutRoot = dir.Substring(root.Length);       
    
    string firstDir = pathWithoutRoot.Split(Path.DirectorySeparatorChar).First();
    

    【讨论】:

    • GetPathRoot on "/a/b" 返回 "\"。无论 OP 想要什么,我很确定不是那样......
    【解决方案5】:

    假设您有一个名为 paths 的路径列表,您可以执行以下操作:

    string currentDirectory = "/";
    var distinctDirectories = paths.Where(p => p.StartsWith(currentDirectory)
                                   .Select(p => GetFirstSubDir(p, currentDirectory)).Distinct();
    
    
    ...
    
    
    string GetFirstSubDir(string path, string currentDirectory)
    {
        int index = path.IndexOf('/', currentDirectory.Length);
        if (index >= 0)
            return path.SubString(currentDirectory.Length - 1, index + 1 - currentDirectory.Length);
        return path.SubString(currentDirectory.Length - 1);
    }
    

    【讨论】:

    • 我正在寻找指定目录之后的第一个目录。例如,我的起始目录可能是 /test/ 并且从路径列表中我正在寻找以 /test/ 开头的不同第一个目录的列表,这有意义吗?
    • @michael_clarke,我相应地更新了我的答案(未经测试的代码)
    • 这就是我的目标。我会尝试一下,看看它是如何工作的。
    猜你喜欢
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2014-03-07
    • 2013-07-08
    相关资源
    最近更新 更多