C# 新手 - 用于构建简单列表对象的对象列表.一个从另一个构建



大家好,我精神上卡住了

 

我有一个从 Web API 检索的对象列表,该 API 具有三个值,分别由父 ID 和字符串值以及行 ID 组成

 

即:

类别 ID 名称        父 ID        

                             1 工具 0                   

2 锤子              1                            

3 螺丝刀         1                            

4 菲利普斯                 3                            

                             5 标准 3             

6 #2                      4                            

7 梅花                    3                            

8 #15                    7                            

 

等。

这需要放入一个简单的列表对象中,该对象由 ParentID 和直接类别名称和父 ID 的串联字符串组成

 

类别 ID                         完整类别名称

                                              0 工具

                                            2 工具/锤子

                                              3 工具/螺丝刀

                                              4 工具/螺丝刀/十字

                                             5 工具/螺丝刀/标准

                                            6 工具/螺丝刀/十字/#2

                                              7 工具/螺丝刀/梅花

                                              8 工具/螺丝刀/梅花/#15

 

 

我希望您能够看到的是,我需要类别 ID 和基于带有斜杠的父 ID 的完整路径。

 

被调用的 API 类

public class Categories_Web
{
public string CategoryName { get; set; }
public int CategoryParent { get; set; }
public int CategoryID { get; set; }
}

具有串联名称的简化类

public class WebCategoriesSimple
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}

我希望这是有道理的,并感谢您的帮助!

你有一个层次结构,只要你有这个层次结构,你就可以考虑递归 - 一个调用自己的方法。您并不总是希望使用递归,但对于可管理的大小列表或尾部调用优化的递归方法,它是一个强大的工具。

下面是输出的演示代码:

Category: 1, Hierarchy: Tools
Category: 2, Hierarchy: Tools/Hammer
Category: 3, Hierarchy: Tools/ScrewDriver
Category: 4, Hierarchy: Tools/ScrewDriver/Phillips
Category: 5, Hierarchy: Tools/ScrewDriver/Standard
Category: 6, Hierarchy: Tools/ScrewDriver/Phillips/#2
Category: 7, Hierarchy: Tools/ScrewDriver/Torx
Category: 8, Hierarchy: Tools/ScrewDriver/Torx/#15

(注意,我认为您的"0,工具"的示例输出不正确)

该程序创建一个硬编码的ProductDef列表。你的可能来自数据库或其他东西。

然后,它会创建一个空的ProductHierarchy列表,该列表将在递归操作运行时填充。

然后,它通过第一次调用Build()开始递归。在该方法中,当传入的项在层次结构中具有父项时,它将调用自身。

当没有更多的父项时,它会将该项目添加到ProductHierarchy列表中。

void Main()
{
List<ProductDef> pdefs = new List<UserQuery.ProductDef>{
new ProductDef{Category = 1, Product = "Tools",  ParentCategory = 0},
new ProductDef{Category = 2, Product = "Hammer",  ParentCategory = 1},
new ProductDef{Category = 3, Product = "ScrewDriver",  ParentCategory = 1},
new ProductDef{Category = 4, Product = "Phillips",  ParentCategory = 3},
new ProductDef{Category = 5, Product = "Standard",  ParentCategory = 3},
new ProductDef{Category = 6, Product = "#2",  ParentCategory = 4},
new ProductDef{Category = 7, Product = "Torx",  ParentCategory = 3},
new ProductDef{Category = 8, Product = "#15",  ParentCategory = 7}
};
//This will get filled as we go
List<ProductHierarchy> phlist = new List<UserQuery.ProductHierarchy>();
//kick off the recursion
foreach (var element in pdefs)
{
Build(element, pdefs, element.Product, element.Category, phlist);
}
//do stuff with your list
foreach (ProductHierarchy ph in phlist)
{
Console.WriteLine(ph.ToString());
}
}
class ProductDef
{
public int Category { get; set; }
public string Product { get; set; }
public int ParentCategory { get; set; }
}
class ProductHierarchy
{
public int Category { get; set; }
public string Hierarchy { get; set; }
public override string ToString()
{
return $"Category: {Category}, Hierarchy: {Hierarchy}";
}
}
void Build(ProductDef def, List<ProductDef> lst, string fullname, int cat, List<ProductHierarchy> phlist)
{
string fullprodname = fullname;
//obtain the parent category of product
var parent = lst.FirstOrDefault(l => l.Category == def.ParentCategory);
if (parent != null)
{
fullprodname = $"{parent.Product}/{fullprodname}";
//recurse the call to see if the parent has any parents
Build(parent, lst, fullprodname, cat, phlist);
}
else
{
//No further parents found, add it to a list
phlist.Add( new ProductHierarchy { Category = cat, Hierarchy = fullprodname }); 
}
}

这是我认为 LINQ 非常适合解决的问题之一。我在理解数据格式时遇到了一些麻烦。但是,可以将投影与 LINQ 结合使用,将原始列表的结果投影到包含基于类定义的新对象或新的匿名类的新列表中。

使用 LINQ 投影到新的匿名类中将如下所示。请记住,我们不知道您的对象名称,因为您没有提供该信息,因此您可能需要从我的示例中进行一些推断。

(请注意,我重读了您的帖子,我想我理解您的原始对象可能被称为什么,因此该帖子已被编辑为使用您的类名。

var newListOfStuff = originalListOfStuff.Select(s => new {
CategoryID = s.CategoryID,
CategoryName = $"Tools/{s.CategoryName}/#{s.CategoryParent}"
});

字符串是使用字符串内插创建的,这在 C# 中是新的。如果你的 C# 版本不支持此功能,则可以使用字符串。改为格式化,如下所示:

string.Format("Tools/{0}/#{1}", s.CategoryName, s.CategoryParent);

使用该新列表,您可以遍历它并使用如下所示的属性:

foreach(var item in newListOfStuff)
{
Console.WriteLine(item.CategoryID);
Console.WriteLine(item.CategoryName);
}

这里有一个类似的答案供参考: https://stackoverflow.com/a/9885766/3096683