C# 在项目列表中迭代到其父级和父级到父级

C# 在项目列表中迭代到其父级和父级到父级,c#,generics,collections,C#,Generics,Collections,我有一个需求,需要遍历具有n级层次结构的项目列表,并且我希望获得所选项目ID的自底向上元素 例如,以下是原始数据 ID ParentID ItemName Category 1 -1 Chai Breweries 4 -1 Mouse-pad Electronic 3 1 GST Taxes 2

我有一个需求,需要遍历具有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和plus-LINQ的selectmany,但使用这个选项,我只能获取当前项,如果当前项没有关联的类别,则不能获取父类别值。 还尝试添加递归方法,但不确定如何构建最终输出,使用递归我们应该只获取当前项

好的,根据下面的注释,我使用了递归函数,如下所示

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; }
}
类程序
{
静态void Main(字符串[]参数)
{
int categoryId=202;
var products=GetProducts();
var product=products.FirstOrDefault(p=>p.ID==categoryId);
var output=getProductiveRecursive(products,categoryId,string.Empty);
控制台写入线(输出);
Console.Read();
}
以递归方式获取公共静态字符串(列出产品、int-parentId、字符串输出)
{
var product=products.FirstOrDefault(p=>p.ParentID==ParentID);
StringBuilder StringBuilder=新的StringBuilder();
if(string.IsNullOrEmpty(product.Category))
{
if(string.IsNullOrEmpty(输出))
{
stringBuilder.Append($”ParentCategoryID={product.ParentID},Name={product.ItemName},Keywords=“);
以递归方式获取产品(products、product.ParentID、stringBuilder.ToString());
}
其他的
以递归方式获取产品(products、product.ParentID、output);
}
其他的
追加($“{output}{product.Category}”);
返回stringBuilder.ToString();
}
公共静态列表GetProducts()
{
var products=新列表();
添加(新产品{ID=1,ParentID=-1,ItemName=“Chai”,Category=“Breweries”});
添加(新产品{ID=4,ParentID=-1,ItemName=“鼠标垫”,Category=“Electronic”});
添加(新产品{ID=3,ParentID=1,ItemName=“GST”,Category=“Taxes”});
Add(新产品{ID=2,ParentID=1,ItemName=“Spices”});
Add(新产品{ID=5,ParentID=4,ItemName=“Mobile”});
products.Add(新产品{ID=6,ParentID=3,ItemName=“我的税”});
退货产品;
}
}
公共类产品
{
公共int ID{get;set;}
public int ParentID{get;set;}
公共字符串ItemName{get;set;}
公共字符串类别{get;set;}
}

然而,在一次迭代中,它返回parentID的Category,但由于它在递归中,它会继续完成早期迭代的工作,因此在这一点上,Category是all time returns”“(empty.string)

,没有任何代码,我只能为您的问题提供一个“默认”答案

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


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

确定最终使它使用正确的逻辑工作,工作代码如下所示

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; }
}
类程序
{
静态void Main(字符串[]参数)
{
int productId=6;
var products=GetProducts();
var product=products.FirstOrDefault(p=>p.ID==productId);
var output=getProductiveRecursive(products,productId,string.Empty);
控制台写入线(输出);
Console.Read();
}
以递归方式获取公共静态字符串(列出产品、int-Id、字符串输出)
{
var product=products.FirstOrDefault(p=>p.ID==ID);
StringBuilder StringBuilder=新的StringBuilder();
if(string.IsNullOrEmpty(输出))
output=stringBuilder.Append($”ParentCategoryID={product.ParentID},Name={product.ItemName},Keywords=“).ToString();
if(string.IsNullOrEmpty(product.Category))
{
递归返回getProductively(products,product.ParentID,output);
}
其他的
输出+=$“{product.Category}”;
返回输出;
}
公共静态列表GetProducts()
{
var products=新列表();
添加(新产品{ID=1,ParentID=-1,ItemName=“Chai”,Category=“Breweries”});
添加(新产品{ID=4,ParentID=-1,ItemName=“鼠标垫”,Category=“Electronic”});
添加(新产品{ID=3,ParentID=1,ItemName=“GST”,Category=“Taxes”});
Add(新产品{ID=2,ParentID=1,ItemName=“Spices”});
Add(新产品{ID=5,ParentID=4,ItemName=“Mobile”});
products.Add(新产品{ID=6,ParentID=3,ItemName=“我的税”});
退货产品;
}
}
公共类产品
{
公共int ID{get;set;}
public int ParentID{get;set;}
公共字符串ItemName{get;set;}
公共字符串类别{get;set;}
}

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

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}");

你试过什么?什么对您不起作用?我曾尝试使用List和plus LINQ的select many,但使用此选项,我只能获取当前项目,但如果当前项目没有关联的类别,则无法获取父类别值。请将其写在您的问题中,并准确说明出现了什么问题。如果您正在寻找一个没有帮助的单行程序,我建议您研究递归函数或它们的替代方法,使用一些局部状态和while循环。select many不适用