【问题标题】:C# Newbie - List of Objects to build simple List Objects. Build one from another [closed]C# Newbie - 用于构建简单列表对象的对象列表。从另一个构建一个[关闭]
【发布时间】:2018-03-18 02:52:16
【问题描述】:

大家好,我被困住了

 

我有一个从 Web API 检索到的对象列表,该列表具有三个值,包括父 ID、字符串值和行 ID

 

IE:

CategoryID        姓名        ParentID

1                           工具             0

2                           锤子             1

3                           螺丝刀      1

4                           菲利普斯                3

5                           标准             3

6                           #2               4

7                           Torx               3

8                          #15              7

 

等等

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

 

CategoryID                        FullCategoryName

0                                            工具

2                                           工具/锤子

3                                             工具/螺丝刀

4                                             工具/螺丝刀/菲利普斯

5                                          工具/螺丝刀/标准件

6                                           工具/螺丝刀/菲利普斯/#2

7                                             工具/螺丝刀/Torx

8                                            工具/螺丝刀/Torx/#15

 

 

我希望您能看到,我需要 categoryID 和基于 parentID 的完整路径并带有斜线。

 

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

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

【问题讨论】:

标签: c#


【解决方案1】:

你所拥有的是一个层次结构,无论何时你都可以考虑递归 - 一种调用自身的方法。您并不总是想使用递归,但对于可管理大小的列表或尾调用优化的递归方法,它是一个强大的工具。

这是输出的演示代码:

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

【讨论】:

  • 你是炸弹!!!这是完美的......无需更改或编辑单个项目!非常感谢!
  • Crowcoder... 这是完美的!谢谢你的帮助!过去两天很难得到这个。在带有 CTE 的 SQL 中,这很容易,但这来自 Web API 返回。我正在编写代码以将其填充到临时表中并对其进行查询。再次感谢
  • 不客气,这是一个有趣的挑战。
【解决方案2】:

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

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

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

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

字符串是使用字符串插值创建的,这是 C# 中的新功能。如果您的 C# 版本不支持,您可以使用 string.Format 代替,如下所示:

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

【讨论】:

  • 感谢您的回答……这很接近,我同意,从我对 LINQ 的了解来看,这是要走的路!!!在层次关系中的 SQL 中,您可以将 ChildID 连接回 ParentID,在这种情况下,父级是 ParentCategoryID,而 ChildID 是 CategoryID。然后知道关系通过连接类别名称继续引用。这是为了生成一种面包屑轨迹……这有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2019-10-26
  • 2019-06-16
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2023-03-14
  • 2021-01-25
相关资源
最近更新 更多