【问题标题】:C# retrieve parent-child url from full url using recursivelyC# 使用递归从完整 url 中检索父子 url
【发布时间】:2021-02-02 11:49:31
【问题描述】:

我需要你的帮助来从完整的 URL 中获取父子 URL 列表,可能是递归使用。 例如,下面是平面结构中的 URL。我必须使用子结构的内部级别以父子形式解析。

  • https://domain/UrlA/UrlA_L1/UrlA_L1_L2
  • https://domain/UrlA/UrlA_L1/UrlA2_L1_L2
  • https://domain/UrlB/UrlB_L1/UrlB_L1_L2
  • https://domain/UrlC/UrlC_L1/UrlC_L1_L2
  • https://domain/UrlD/UrlD_L1/UrlD_L1_L2/UrlD_L1_L2_L3
  • https://domain/UrlE/UrlE_L1/UrlE_L1_L2/UrlE_L1_L2_L3
  • https://domain/UrlF/UrlF_L1/UrlF_L1_L2/UrlF_L1_L2_L3

进入具有父子关系的 URL 列表。

public class HtmlSiteMap
{
  public string Url { get; set; }
  public string PageTitle { get; set; }
  public int UrlLevel { get; set; }
  public List<HtmlSiteMap> Childrens { get; set; }
}

我的预期输出

{
Url: https://domain/UrlA,
PageTitle : UrlA,
UrlLevel : 0 ,
Childrens : { 
      Url : https://domain/UrlA/UrlA_L1,
      PageTitle : UrlA_L1,
      UrlLevel : 1,
      Childrens : { 
                   Url : https://domain/UrlA/UrlA_L1/UrlA_L1_L2,
                   PageTitle : UrlA_L1_L2,
                   UrlLevel : 2,
                   Childrens : null
                  },
                  { 
                   Url : https://domain/UrlA/UrlA_L1/UrlA2_L1_L2,
                   PageTitle : UrlA2_L1_L2,
                   UrlLevel : 2,
                   Childrens : null
                  }
   },
Url: https://domain/UrlB,
PageTitle : UrlB,
UrlLevel : 0 ,
Childrens : {
             Url : https://domain/UrlB/UrlB_L1,
             PageTitle : UrlB_L1,
             UrlLevel : 1,
             Childrens : {
                         Url : https://domain/UrlB/UrlB_L1/UrlB_L1_L2,
                          PageTitle : UrlB_L1_L2,
                          UrlLevel : 2,
                          Childrens : null
                         }
            }
.................
.................
..................
}

我试图通过拆分和递归来实现。但无法得到结果。您的帮助将不胜感激。

【问题讨论】:

    标签: c# asp.net-mvc asp.net-web-api


    【解决方案1】:

    这是另一个反向解决方案。我正在研究预排序列表,构建从根到叶的节点。这段代码在递归中看起来更易被初学者阅读和理解。

    static void Main(string[] args)
    {
        var input = new[]
        {
            new Uri("https://domain/UrlA/UrlA_L1/UrlA_L1_L2"),
            new Uri("https://domain/UrlA/UrlA_L1/UrlA2_L1_L2"),
            new Uri("https://domain/UrlB/UrlB_L1/UrlB_L1_L2"),
            new Uri("https://domain/UrlC/UrlC_L1/UrlC_L1_L2"),
            new Uri("https://domain/UrlD/UrlD_L1/UrlD_L1_L2/UrlD_L1_L2_L3"),
            new Uri("https://domain/UrlE/UrlE_L1/UrlE_L1_L2/UrlE_L1_L2_L3"),
            new Uri("https://domain/UrlF/UrlF_L1/UrlF_L1_L2/UrlF_L1_L2_L3")
        };
        
        var rows = input.Select(u => u.AbsolutePath.Substring(1))
            .OrderBy(s => s).Select(s => s.Split('/')).ToList();
        
        var rootNodes = new List<HtmlSiteMap>();
        ProcessNodes(rootNodes, rows, 
            input.Select(u => $"{u.Scheme}://{u.Host}/").Distinct().FirstOrDefault(), 0);
    
        foreach (var node in rootNodes)
            Console.WriteLine(node.ToString());
    }
    
    static void ProcessNodes(List<HtmlSiteMap> children, List<string[]> rows, string prefix, int level)
    {
        if (rows.Count == 0)
            return;
        HtmlSiteMap currentNode = null;
        var subRows = new List<string[]>();
        foreach (var parts in rows)
        {
            if (parts.Length == 0)
                continue;
            subRows.Add(parts.Skip(1).ToArray());
            
            if (currentNode != null && currentNode.PageTitle == parts[0])
                continue;
            
            if(currentNode != null)
                ProcessNodes(currentNode.Children, subRows, prefix + currentNode.PageTitle + "/", level + 1);
    
            currentNode = new HtmlSiteMap
            {
                Url = prefix + parts[0],
                PageTitle = parts[0],
                UrlLevel = level
            };
            children.Add(currentNode);
            subRows.Clear();
        }
        
        if(currentNode != null && subRows.Count > 0)
            ProcessNodes(currentNode.Children, subRows, prefix + currentNode.PageTitle + "/", level + 1);
    }
    
    public class HtmlSiteMap
    {
        public string Url { get; set; }
        public string PageTitle { get; set; }
        public int UrlLevel { get; set; }
        //Also renamed this from Childrens to Children
        public List<HtmlSiteMap> Children { get; set; }
    
        public HtmlSiteMap()
        {
            Children = new List<HtmlSiteMap>();
        }
    
        //Borrowed this from previous answer
        public override string ToString()
        {
            var shift = new string(' ', UrlLevel);
            var sb = new StringBuilder();
            sb.AppendLine(shift + $"Url: {Url},");
            sb.AppendLine(shift + $"PageTitle: {PageTitle},");
            sb.AppendLine(shift + $"UrlLevel: {UrlLevel},");
            sb.AppendLine(shift + "Children:");
            if (Children.Count == 0)
            {
                sb.AppendLine(shift + "-");
            }
            else
            {
                foreach (var child in Children)
                {
                    sb.AppendLine(child.ToString());
                }
            }
            return sb.ToString();
        }
    }
    

    【讨论】:

    • 谢谢。这非常简单易懂。
    【解决方案2】:

    基本版本(没有错误处理)可能如下所示:

       static void Main(string[] args)
        {
            var input = new List<string>
            {
                "https://domain/UrlA/",
                "https://domain/UrlA/UrlA_L1/",
                "https://domain/UrlA/UrlA_L1/UrlA_L1_L2",
                "https://domain/UrlA/UrlA_L1/UrlA2_L1_L2",
                "https://domain/UrlB",
                "https://domain/UrlB/UrlB_L1",
                "https://domain/UrlB/UrlB_L1/UrlB_L1_L2",
                "https://domain/UrlC/UrlC_L1/UrlC_L1_L2",
                "https://domain/UrlD/UrlD_L1/UrlD_L1_L2/UrlD_L1_L2_L3",
                "https://domain/UrlE/UrlE_L1/UrlE_L1_L2/UrlE_L1_L2_L3",
                "https://domain/UrlF/UrlF_L1/UrlF_L1_L2/UrlF_L1_L2_L3"
            };
    
            var output = new List<HtmlSiteMap>();
    
            foreach (var url in input)
            {
                var parts = url.Split(@"/", StringSplitOptions.RemoveEmptyEntries);
                var current = new HtmlSiteMap
                {
                    Url = url,
                    PageTitle = parts[^1]                    
                };
    
                var parentName = parts[^2];
    
                static HtmlSiteMap FindParent(List<HtmlSiteMap> score, string name)
                {
                    foreach (var item in score)
                    {
                        if (item.PageTitle == name)
                        {
                            return item;
                        }
                        var inChild = FindParent(item.Childrens, name);
                        if (inChild != null)
                        {
                            return inChild;
                        }
                    }
                    return null;
                }
    
                var parent = FindParent(output, parentName);
                if (parent == null)
                {
                    current.UrlLevel = 1;
                    output.Add(current);
                }
                else
                {
                    current.UrlLevel = parent.UrlLevel + 1;
                    parent.Childrens.Add(current);
                }
            }
    
    
            foreach (var current in output)
            {
                Console.WriteLine(current.ToString());
            }
            Console.ReadLine();
        }
    
    
        public class HtmlSiteMap
        {
            public string Url { get; set; }
            public string PageTitle { get; set; }
            public int UrlLevel { get; set; }
            public List<HtmlSiteMap> Children { get; set; }
    
            public HtmlSiteMap()
            {
                Children = new List<HtmlSiteMap>();
            }
    
            public override string ToString()
            {
                var shift = new string(' ', UrlLevel);
                var sb = new StringBuilder();
                sb.AppendLine(shift + $"Url: {Url},");
                sb.AppendLine(shift + $"PageTitle: {PageTitle},");
                sb.AppendLine(shift + $"UrlLevel: {UrlLevel},");
                sb.AppendLine(shift + "Children:");
                if (Children.Count == 0)
                {
                    sb.AppendLine(shift + "-");
                }
                else
                {
                    foreach (var child in Children)
                    {
                        sb.AppendLine(child.ToString());
                    }
                }
                return sb.ToString();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2011-06-21
      • 2013-10-12
      • 2012-05-08
      • 1970-01-01
      • 2016-02-10
      • 2017-05-11
      • 1970-01-01
      • 2018-05-20
      • 1970-01-01
      相关资源
      最近更新 更多