将数据表转换为树状类结构

本文关键字:结构 数据表 转换 | 更新日期: 2023-09-27 17:59:21

我有这个数据表

Name    Amount  Category
sample  100.00  1
sample  100.00  1
aasdas  11.00   1
asd     1.00    2
sadjas  1.00    2
sadjas  1.00    2
asdasd  1.00    3
asdasd  1.00    3
test    10.00   3

我有这类

public class ProductListModel
{
    public string CategoryName { get; set; }
    public List<ProductModel> prodList { get; set; }
}

这个类的每个实例都包含一个具有这个定义的产品模型列表

public class ProductModel
{
    public string Name{ get; set; }
    public double Amount { get; set; }
}

如何转换此数据表以适应ProductListModel类的定义?

因此输出将是这种形式(仅用于可视化):

// Group by category 1
-- ProductListModel
     --CategoryName = 1
     -- ProdList 
        -- Name = sample, amount = 100.00       
        -- Name = sample, amount = 100.00       
        -- Name = aasdas, amount = 11.00   
// Group by category 2
-- ProductListModel
     --CategoryName = 2
     -- ProdList 
        -- Name = asd, amount = 1.00       
        -- Name = sadjas, amount = 1.00       
        -- Name = sadjas, amount = 1.00      
// Group by category 3      
-- ProductListModel
     --CategoryName = 3
     -- ProdList 
        -- Name = asdasd, amount = 1.00       
        -- Name = asdasd, amount = 1.00      

我试过了,但被卡住了:p

将数据表转换为树状类结构

你可以像这个一样"简化"它

var productList = datatable.Rows.Cast<DataRow>()
    .GroupBy(r => r["Category"] + "").Select(g => new ProductListModel {
        CategoryName = g.Key,
        prodList = g.Select(r => new ProductModel {
            Name = r["Name"] + "",
            Amount = (double)r["Amount"]
        }).ToList()
    }).ToList();

会是这样吗?这将把类别放在一个列表中,并把相应的产品放在类别中。(这是未经测试的)

List<ProductListModel> productCategories = new List<ProductListModel>();
foreach (DataRow row in dataTable.Rows) // Go through all data rows
{
    if (!productCategories.Any(pc => pc.CategoryName == (string)row[2])) // if the product's category is not registered
        productCategories.Add(new ProductListModel() { CategoryName = (string)row[2] } ); // Then add the category to the category list
    // Add the current product (row) to the first registered category that matches the product's own
    productCategories.First(pc => pc.CategoryName == (string)row[2]).prodList.Add(new ProductModel() 
    { 
        Name = (string)row[0], 
        Amount = double.Parse((string)row[1]) 
    }); 
}

我希望这能有所帮助。

编辑

我稍微修改了一下代码,这样重复的产品就会堆叠弹药(如果这有意义的话):

List<ProductListModel> productCategories = new List<ProductListModel>();
foreach (DataRow row in dataTable.Rows)
{
    if (!productCategories.Any(pc => pc.CategoryName == (string)row[2]))
        productCategories.Add(new ProductListModel() { CategoryName = (string)row[2] });
    ProductListModel currentCategory = productCategories.First(pc => pc.CategoryName == (string)row[2]);
    if (currentCategory.prodList.Any(pr => pr.Name == (string)row[0]))
        currentCategory.prodList.First(pr => pr.Name == (string)row[0]).Amount += double.Parse((string)row[1]);
    else
        currentCategory.prodList.Add(new ProductModel() { Name = (string)row[0], Amount = double.Parse((string)row[1]) });
}

我像这个一样解决了它

List<ProductListModel> productList = new List<ProductListModel>();
foreach (var row in datatable.AsEnumerable())
{
    var categoryId = row.Field<string>("Category");
    var product = new ProductModel
    {
        Name = row.Field<string>("Name"),
        Amount = row.Field<double>("Amount")
    };
    // Build each category
    if (!productList.Any(x => x.CategoryName == categoryId))
    {
        var itemList = new List<ProductModel>();
        itemList.Add(product);
        productList.Add(new ProductListModel { CategoryName = categoryId, prodList = itemList });
    }
    else
    {
        var existingprodList = productList.Where(x => x.CategoryName == categoryId).FirstOrDefault();
        existingprodList.prodList.Add(product);
    }
}