【问题标题】:Iterate through list of items to their parent and parent to parent level遍历项目列表到其父级和父级到父级
【发布时间】:2021-07-15 13:07:20
【问题描述】:

我有一个要求是遍历具有 n 级层次结构的项目列表,我想获取所选项目 ID 的自下而上元素。

例如以下是原始数据

ID         ParentID    ItemName       Category
1          -1          Chai           Breweries
4          -1          Mouse-pad      Electronic
3           1          GST            Taxes
2           1          Spices         
5           4          Mobile         
6           3          My Tax         

我想在 C# 中进行编程以迭代和显示例如如果我为方法 6 传递 ID 参数,那么它应该打印输出如下

ParentID=3, Name=My Tax, Category=Taxes

如果我将 ID 参数作为 2 传递,那么输出应该是相似的

ParentID=1, Name=Spices, Category=Breweries

请帮助我实现此功能,可能是使用通用集合或任何算法都会有所帮助

我尝试过的是 我曾尝试使用 List 并加上 LINQ 的 select many,但使用此选项,我只能获取当前项目,但如果当前项目没有与之关联的类别,则不能获取父类别值。 还尝试添加递归方法,但不确定如何构建最终输出,使用递归我们应该只获取当前项目。

好的,按照下面的cmets,我使用了如下的递归函数

class Program
{
    static void Main(string[] args)
    {
        int categoryId = 202;
        var products = GetProducts();
        var product = products.FirstOrDefault(p => p.ID == categoryId);

        var output = GetProductRecursively(products, categoryId, string.Empty);
        Console.WriteLine(output);
        Console.Read();
    }

    public static string GetProductRecursively(List<Product> products, int parentId, string output)
    {
        var product = products.FirstOrDefault(p => p.ParentID == parentId);
        StringBuilder stringBuilder = new StringBuilder();
        if (string.IsNullOrEmpty(product.Category))
        {
            if (string.IsNullOrEmpty(output))
            {
                stringBuilder.Append($"ParentCategoryID={ product.ParentID}, Name={ product.ItemName}, Keywords=");
                GetProductRecursively(products, product.ParentID, stringBuilder.ToString());
            }
            else
                GetProductRecursively(products, product.ParentID, output);
        }
        else
            stringBuilder.Append($"{output}{product.Category}");
        return stringBuilder.ToString();
    }
    public static List<Product> GetProducts()
    {
        var products = new List<Product>();
        products.Add(new Product { ID = 1, ParentID = -1, ItemName = "Chai", Category = "Breweries" });
        products.Add(new Product { ID = 4, ParentID = -1, ItemName = "Mouse-pad", Category= "Electronic" });
        products.Add(new Product { ID = 3, ParentID  = 1, ItemName = "GST", Category= "Taxes" });
        products.Add(new Product { ID = 2, ParentID = 1, ItemName = "Spices" });
        products.Add(new Product { ID = 5, ParentID = 4, ItemName = "Mobile" });
        products.Add(new Product { ID = 6, ParentID = 3, ItemName = "My Tax" });
        return products;
    }
}

public class Product
{
    public int ID { get; set; }
    public int ParentID { get; set; }
    public string ItemName { get; set; }
    public string Category { get; set; }
}

然而,在一次迭代中,它返回父 ID 的类别,但由于它处于递归状态,它会继续完成其早期迭代的工作,因此在这一点上,类别总是返回 ""(empty.string)

【问题讨论】:

  • 你试过什么?什么不适合你?
  • 我尝试过使用 List 并加上 LINQ 的 select many,但使用此选项我只能获取当前项目,但如果当前项目没有与之关联的类别,则不能获取父类别值.
  • 在你的问题中写下,并准确说明哪里出了问题。如果您正在寻找一种无济于事的单线。
  • 我建议您研究递归函数或它们与某些本地状态和 while 循环的替代方案。
  • select many 在这里不适用。您需要写下您的逻辑以找到具有 category!=null 的父级,可能使用循环或递归方法。一个有用的提示是“如果你想不出没有 Linq 的逻辑,那么使用 Linq 将无法实现。”

标签: c# generics collections


【解决方案1】:

非递归解决方案可能如下所示:

var productId = 6;
var products = GetProducts();

var productDict = products // create dictionary to search for products by id
    .GroupBy(p => p.ID)
    .ToDictionary(p => p.Key, g => g.First());

var product = productDict[productId];

// create loop state variables 
string category = null; 
var currProduct = product;
// cycle while category not found   
while (category == null)
{
    // or there is no parent product
    if (!productDict.ContainsKey(currProduct.ParentID))
    {
        break;
    }

    currProduct = productDict[currProduct.ParentID];
    category = currProduct.Category;
}

Console.WriteLine($"{category}-{product.ItemName}");

【讨论】:

    【解决方案2】:

    没有任何代码,我只能针对你的问题给你一个“默认”的答案。

    要解决您的问题,您必须在您的类中实现一个函数来获取您的实例的父级。

    要获得绝对父级(对象本身没有父级),您必须实现一个函数,只要它有父级,它就会调用自己。

    【讨论】:

      【解决方案3】:

      好的,终于让它使用正确的逻辑,工作代码如下

      class Program
      {
          static void Main(string[] args)
          {
              int productId = 6;
              var products = GetProducts();
              var product = products.FirstOrDefault(p => p.ID == productId);
      
              var output = GetProductRecursively(products, productId, string.Empty);
              Console.WriteLine(output);
              Console.Read();
          }
      
          public static string GetProductRecursively(List<Product> products, int Id, string output)
          {
              var product = products.FirstOrDefault(p => p.ID == Id);
              StringBuilder stringBuilder = new StringBuilder();
              if (string.IsNullOrEmpty(output))
                  output = stringBuilder.Append($"ParentCategoryID={ product.ParentID}, Name={ product.ItemName}, Keywords=").ToString();
              if (string.IsNullOrEmpty(product.Category))
              {
                  return GetProductRecursively(products, product.ParentID, output);
              }
              else
                  output += $"{product.Category}";
              return output;
          }
          public static List<Product> GetProducts()
          {
              var products = new List<Product>();
              products.Add(new Product { ID = 1, ParentID = -1, ItemName = "Chai", Category = "Breweries" });
              products.Add(new Product { ID = 4, ParentID = -1, ItemName = "Mouse-pad", Category = "Electronic" });
              products.Add(new Product { ID = 3, ParentID = 1, ItemName = "GST", Category = "Taxes" });
              products.Add(new Product { ID = 2, ParentID = 1, ItemName = "Spices" });
              products.Add(new Product { ID = 5, ParentID = 4, ItemName = "Mobile" });
              products.Add(new Product { ID = 6, ParentID = 3, ItemName = "My Tax" });
              return products;
          }
      }
      
      public class Product
      {
          public int ID { get; set; }
          public int ParentID { get; set; }
          public string ItemName { get; set; }
          public string Category { get; set; }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-27
        • 2019-05-31
        • 2020-10-31
        • 2019-11-19
        相关资源
        最近更新 更多