c# - 如何从表示 C# 或 VB 中的目录结构的字符串列表创建集合

标签 c# list collections recursion directory

首先,我检查了this post但它是在 Python 中,首先,其次它似乎实际上是在创建目录,在这种情况下我无法做到这一点。

其次,这些目录不存在,我也无法创建它们。

我有一个 C# 输入,如下所示:

        List<string> filePaths = new List<string>();
        filePaths.Add(@"ProgramDir\InstallDir\Module1\mod1pack1.exe");
        filePaths.Add(@"ProgramDir\InstallDir\Module1\mod1pack2.exe");
        filePaths.Add(@"ProgramDir\InstallDir\Module2\mod2pack1.exe");
        filePaths.Add(@"ProgramDir\InstallDir\Module1\SubModule1\report1.rpt");
        filePaths.Add(@"SystemDir\DependencyDir\dependency1.dll");
        filePaths.Add(@"SystemDir\DependencyDir\dependency2.dll");

我一直在尝试做的是创建一个代表此结构的对象,以便它可以像这样可视化:

-ProgramDir
    Installdir
        Module1
            mod1pack1.exe
            mod1pack2.exe
            -SubModule1
                 report1.rpt
        Module2
            mod2pack1.exe
-SystemDir
    -DependencyDir
         dependency1.dll
     dependency2.dll

我尝试过以下的各种版本,我真的可以使用一些帮助来找出我哪里出错了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SetFilePathList();
            DTree forest = new DTree();
            List<DTreeBranch> branches = new List<DTreeBranch>();
            foreach (string path in filePaths)
            {
                forest.GrowTree(path.Split('\\'), branches);
            }
            forest.SubBranches.AddRange(branches);
        }
        private static List<string> filePaths { get; set; }
        private static void SetFilePathList()
        {
            filePaths = new List<string>();
            filePaths.Add(@"ProgramDir\InstallDir\Module1\mod1pack1.exe");
            filePaths.Add(@"ProgramDir\InstallDir\Module1\mod1pack2.exe");
            filePaths.Add(@"ProgramDir\InstallDir\Module2\mod2pack1.exe");
            filePaths.Add(@"ProgramDir\InstallDir\Module1\SubModule1\report1.rpt");
            filePaths.Add(@"SystemDir\DependencyDir\dependency1.dll");
            filePaths.Add(@"SystemDir\DependencyDir\dependency2.dll");
        }
    }
    public class DTree
    {
        public List<DTreeBranch> SubBranches { get; set; }
        public string BranchName { get; set; }
        public DTree() { SubBranches = new List<DTreeBranch>(); }
        public DTreeBranch AddChildren(string[] childElements, DTreeBranch branch)
        {
            DTreeBranch childBranch;
            foreach (string element in childElements)
            {
                childBranch = new DTreeBranch();
                childBranch.BranchName = element;
                branch.SubBranches.Add(childBranch);
                var query = from q in childElements
                            where q != childBranch.BranchName
                            select q;
                AddChildren(query.ToArray<string>(), childBranch);
            }
            return branch;
        }
        public void GrowTree(string[] pathElements, List<DTreeBranch> Branches)
        {
            DTreeBranch result = Branches.Find(delegate(DTreeBranch b)
            {
                return b.BranchName == pathElements[0];
            });

            if (result == null)
            {
                DTreeBranch newRootBranch = new DTreeBranch();
                newRootBranch.BranchName = pathElements[0];
                Branches.Add(newRootBranch);
                GrowTree(pathElements, Branches);
            }
            else
            {
                var query = from q in pathElements
                            where q != result.BranchName
                            select q;
                DTreeBranch childBranch = AddChildren(query.ToArray<string>(), result);
                Branches.Add(childBranch);
            }
        }
    }
    public class DTreeBranch
    {
        public List<DTreeBranch> SubBranches { get; set; }
        public string BranchName { get; set; }
        public DTreeBranch()
        {
            SubBranches = new List<DTreeBranch>();
        }
    }
}

最主要的是输出只有两层深。我想我所说的是新元素被添加到深度,而不是广度,我不知道如何有效地解决这个问题。我还认为我的代码比我需要的多得多。

提前致谢。

最佳答案

我不确定我们的目标是什么,但是一个简单的递归解析就可以很容易地做到这一点。写下来了,希望对你有帮助。如果您愿意,您可以使用 DTree 和子分支,或者文件和目录的单独集合等,使其变得更加奇特。我不太明白其中所有代码的用途。如果它与 WIX 有关,我很抱歉;)并且您始终可以使用类似的方法将其解析到树中,然后将其合理地转换为不同的格式。

  • 这假设没有重复的叶节点(文件名)。
  • 如果不是这种情况,只需添加健全性检查(如目录)。

主要的“Node”类 -

public class Node
{
    public string Name { get; set; }
    public bool IsDirectory { get; set; }
    public List<Node> Children = new List<Node>();

    internal void AddChildren(string f)
    {
        var dirs = Path.GetDirectoryName(f);
        if (string.IsNullOrEmpty(dirs))
        {
            // we are adding a file
            var file = Path.GetFileName(f);
            Children.Add(new Node {Name = file, IsDirectory = false});
        }
        else
        {
            // we are adding a directory
            var firstDir = dirs.Split(Path.DirectorySeparatorChar)[0];
            var childNode = Children.FirstOrDefault(d => d.Name == firstDir);
            if (childNode == null)
            {
                childNode = new Node {Name = firstDir, IsDirectory = true};
                Children.Add(childNode);
            }

            var subPath = f.Substring(firstDir.Length + 1);
            childNode.AddChildren(subPath);
        }
    }
}

调用很简单,如下所示:

var filePaths = new List<string> { 
    @"ProgramDir\InstallDir\Module1\mod1pack1.exe",
    @"ProgramDir\InstallDir\Module1\mod1pack2.exe",
    @"ProgramDir\InstallDir\Module2\mod2pack1.exe",
    @"ProgramDir\InstallDir\Module1\SubModule1\report1.rpt",
    @"SystemDir\DependencyDir\dependency1.dll",
    @"SystemDir\DependencyDir\dependency2.dll",
};

var node = new Node { Name = "Root", IsDirectory = true };
foreach (var f in filePaths )
{
    node.AddChildren(f);
}

打印出来(每层都有缩进,给我这个)

public static void PrintNode(Node node, int indent)
{
    if (indent > 0) // don't print out root directory (level 1). 
    {
        var ending = node.IsDirectory ? Path.DirectorySeparatorChar.ToString() : "*";
        Console.WriteLine("{0}{1}{2}", new string('\t', indent - 1), node.Name, ending);
    }
    node.Children.ForEach(n => PrintNode(n, indent + 1));
}

ProgramDir\
    InstallDir\
            Module1\
                    mod1pack1.exe*
                    mod1pack2.exe*
                    SubModule1\
                            report1.rpt*
            Module2\
                    mod2pack1.exe*
SystemDir\
    DependencyDir\
            dependency1.dll*
            dependency2.dll*

关于c# - 如何从表示 C# 或 VB 中的目录结构的字符串列表创建集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9371541/

相关文章:

c# - 我什么时候使用 Task.Yield()?

c# - 数据访问层(DAL)中的LINQ查询方法

python - 批量更新 Python 列表的一部分

scala - 如何在 Scala 中创建具有有界类型参数的自定义 Seq?

c# - .NET 4.5(或 4.5.1)是否能够与安全协议(protocol)无关?

c# - 为什么在同一个 UI 控件上第二次查询时 WaitForControlExist() 返回 false?

java - 如何在 Windchill GUI 中的列表内添加自定义按钮

python - 使用其他列的值列表创建一个列

javascript - Meteor.js 按字段中的值过滤集合

python - 为什么 Python 不支持记录类型? (即可变的命名元组)