C# 构建目录结构

C# 构建目录结构,c#,recursion,C#,Recursion,我的情况是,我得到了一个代表目录结构的列表,格式如下: "My Folder\Images" "My Folder\Images\Gif" "My Folder\Images\JPG" "My Folder\Media" "My Folder\Media\Mov" "My Folder\Media\Mov\QT" "My Folder\Media\MPG" 对可以嵌套多少层没有限制 我需要构建一个表示树视图的东西,格式如下: public class Folder { public s

我的情况是,我得到了一个代表目录结构的列表,格式如下:

"My Folder\Images"
"My Folder\Images\Gif"
"My Folder\Images\JPG"
"My Folder\Media"
"My Folder\Media\Mov"
"My Folder\Media\Mov\QT"
"My Folder\Media\MPG"
对可以嵌套多少层没有限制

我需要构建一个表示树视图的东西,格式如下:

public class Folder
{
    public string FolderName { get; set; }
    public List<Folder> Folders{ get; set; } // a list of subfolders
}
公共类文件夹
{
公共字符串FolderName{get;set;}
公用列表文件夹{get;set;}//子文件夹列表
}
我只是无法获得构建此功能的重现功能。任何来自大师的帮助都将不胜感激

短暂性脑缺血发作

编辑:我的完整类定义是:

public class Folder
{
    public string Name { get; set; }

    public List<Folder> Folders { get; set; }
    public Folder(List<string> input)
    {
        foreach (var folder in input)
        {
            var delimPos = folder.IndexOf("\\");
            if (delimPos == -1)
            {
                Name = folder ;
            }
            else
            {
                Name = folder.Substring(0, delimPos);
                var subFolders= input.Select(o => o.Substring(delimPos + 1)).ToList();
                Folders= new List<Folder>();
                foreach (var subFolder in subFolders)
                {
                    Folders.Add(new Folder(new List<string>() { subFolder }));
                }

            }
        }
    }
}
公共类文件夹
{
公共字符串名称{get;set;}
公用列表文件夹{get;set;}
公用文件夹(列表输入)
{
foreach(输入中的var文件夹)
{
var delimPos=folder.IndexOf(“\\”);
如果(delimPos==-1)
{
名称=文件夹;
}
其他的
{
Name=folder.Substring(0,delimPos);
var subFolders=input.Select(o=>o.Substring(delimPos+1)).ToList();
文件夹=新列表();
foreach(子文件夹中的var子文件夹)
{
添加(新文件夹(新列表(){subFolder}));
}
}
}
}
}

有关通过字符串解析进行的简单节点遍历,请参考以下示例

private void button1_Click(object sender, EventArgs e)
        {
            var folders = ProcessNode("My Folder\\Media\\Mov\\QT", 0);
            MessageBox.Show("finished");

        }
        private Folder ProcessNode(string input, int index)
        {
            var newIndex = input.IndexOf("\\", index + 1);
            if (newIndex < 0) return new Folder() { FolderName = input.Substring(index, input.Length - index) };
            var nodeName = input.Substring(index, newIndex - index);
            var thisFolder = new Folder()
            {
                FolderName = nodeName,
                Folders = new List<Folder>()
            };
            thisFolder.Folders.Add(ProcessNode(input, newIndex));
            return thisFolder;
        }
private void按钮1\u单击(对象发送者,事件参数e)
{
var folders=ProcessNode(“我的文件夹\\媒体\\Mov\\QT”,0);
MessageBox.Show(“完成”);
}
私有文件夹ProcessNode(字符串输入,int索引)
{
var newIndex=input.IndexOf(“\\”,index+1);
if(newIndex<0)返回新文件夹(){FolderName=input.Substring(index,input.Length-index)};
var nodeName=input.Substring(index,newIndex-index);
var thisFolder=新文件夹()
{
FolderName=nodeName,
文件夹=新列表()
};
添加(ProcessNode(输入,newIndex));
返回此文件夹;
}
如果要使用拆分函数和列表

    private void button1_Click(object sender, EventArgs e)
        {

            var splitted = "My Folder\\Media\\Mov\\QT".Split('\\').ToList();
            var foldersList = ProcessNode(splitted, 0);
            MessageBox.Show("finished");

        }     
private Folder ProcessNode(List<string> input, int index)
            {
                if (index >= input.Count) return null;
                var thisFolder = new Folder()
                {
                    FolderName = input[index],
                    Folders = new List<Folder>()
                };
                thisFolder.Folders.Add(ProcessNode(input, index + 1));
                return thisFolder;
            }
private void按钮1\u单击(对象发送者,事件参数e)
{
var splitted=“My Folder\\Media\\Mov\\QT”.Split('\\').ToList();
var foldersList=ProcessNode(已拆分,0);
MessageBox.Show(“完成”);
}     
私有文件夹ProcessNode(列表输入,int索引)
{
if(index>=input.Count)返回null;
var thisFolder=新文件夹()
{
FolderName=输入[索引],
文件夹=新列表()
};
添加(ProcessNode(输入,索引+1));
返回此文件夹;
}

您当然会遇到这样的问题:在分割和处理
图像\Gif
之后,在分割和处理
图像\JPG
时,您将重新添加另一个
图像
文件夹。第一个将有一个子文件夹
Gif
,第二个将有一个子文件夹
JPG

您可以通过在第一个零件上分组并仅处理以下零件来解决此问题:

public static List<Folder> ParseInputRecursive(string[] input)
{
    var foldersInParts = input.Select(f => f.Split(new [] { '\\' }, StringSplitOptions.RemoveEmptyEntries).ToList()).ToList();

    return ParseInputRecursive(foldersInParts);
}

public static List<Folder> ParseInputRecursive(List<List<string>> input)
{
    var folders = new List<Folder>();

    foreach (var folderPartsGroup in input.GroupBy(p => p[0]))
    {
        var folder = new Folder { Name = folderPartsGroup.Key };

        // Remove parent name, skip parent itself
        var subFolders = folderPartsGroup.Select(f => f.Skip(1).ToList()).Where(f => f.Count > 0).ToList();

        folder.Folders = ParseInputRecursive(subFolders);

        folders.Add(folder);
    }

    return folders;
}
鉴于这一投入:

var input = new string[] 
{
    @"F1\Images",
    @"F1\Images\Gif",
    @"F1\Images\JPG",
    @"F1\Media",
    @"F1\Media\Mov",
    @"F2\Docs",
    @"F2\Docs\Foo",
};
给出此输出:

F1
*Images
**Gif
**JPG
*Media
**Mov
F2
*Docs
**Foo

下面是一个非递归解决方案,它根据需要解析和打印值。如果有帮助,请告诉我

逻辑


共享您的递归函数。让我们看看编辑有什么问题:添加了完整的类定义@我现在有点困惑。您想遍历单个字符串还是字符串列表?我希望每个文件夹都有一个名称属性以及它包含的子文件夹列表(每个子文件夹都有相同的操作)。请查看下面的非递归方法,并让我知道它是否适合您。完美。正是我需要的。
F1
*Images
**Gif
**JPG
*Media
**Mov
F2
*Docs
**Foo
        public static IEnumerable<Folder> Parse(IEnumerable<string> locations)
        {
            var folders = new List<Folder>();
            foreach (var location in locations)
            {
                var parts = location.Split(new[]{Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
                Folder currentFolder = null;
                foreach (var part in parts)
                {
                    var parentFolders = currentFolder!=null ? currentFolder.Folders : folders;
                    currentFolder = parentFolders.Find(folder => folder.Name == part) ?? new Folder { Name = part };
                    if (!parentFolders.Any(folder => folder.Name.Equals(currentFolder.Name)))
                    {
                        parentFolders.Add(currentFolder);
                    }
                }
            }
            return folders;
        }
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
namespace Rextester
{

    public class Folder
    {
        public string Name { get; set; }

        public List<Folder> Folders { get; internal set; }

        public Folder()
        {
            this.Folders = new List<Folder>();
        }

       public static IEnumerable<Folder> Parse(IEnumerable<string> locations)
        {
            var folders = new List<Folder>();
            foreach (var location in locations)
            {
                var parts = location.Split(new[]{Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
                Folder currentFolder = null;
                foreach (var part in parts)
                {
                    var parentFolders = currentFolder!=null ? currentFolder.Folders : folders;
                    currentFolder = parentFolders.Find(folder => folder.Name == part) ?? new Folder { Name = part };
                    if (!parentFolders.Any(folder => folder.Name.Equals(currentFolder.Name)))
                    {
                        parentFolders.Add(currentFolder);
                    }
                }
            }
            return folders;
        }

        public override string ToString()
        {
            if (this.Folders.Count == 0)
            {
                return this.Name;
            }
            else
            {
                var folders = this.Folders
                    .SelectMany(folder => folder.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None))
                    .Select(f => this.Name + Path.DirectorySeparatorChar + f);
                return string.Join(Environment.NewLine, folders);
            }

        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var locationList = new List<string>()
                                   {
                                       @"My Folder\Images",
                                       @"My Folder\Media",
                                       @"My Folder\Images\Gif",
                                       @"My Folder\Images\JPG",
                                       @"My Folder\Media\Mov",
                                       @"My Folder\Media\Mov\QT",
                                       @"My Folder\Media\MPG"
                                   };
            var folderLists = Folder.Parse(locationList);
            Console.WriteLine(string.Join(Environment.NewLine, folderLists));
            Console.ReadLine();
        }
    }
}
My Folder\Images\Gif
My Folder\Images\JPG
My Folder\Media\Mov\QT
My Folder\Media\MPG