阻止项目添加到字典

preventing the item to add to the dictionary

我想在 3 级类别中创建分层列表。

我的数据有以下几种:

var appCategoryList = new List<AppCategoryDataModel>() {
    new AppCategoryDataModel() { AppCategoryId = 4844, ParentappCategoryId = null , AppCategoryName = "ItemResearch", ProtocolId = 5164, ProtocolTitle="ABC: Evaluation" },
    new AppCategoryDataModel() { AppCategoryId = 4844, ParentappCategoryId = null, AppCategoryName = "ItemResearch", ProtocolId = null, ProtocolTitle=""},
    new AppCategoryDataModel() { AppCategoryId = 4845, ParentappCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId = null, ProtocolTitle="" },
    new AppCategoryDataModel() { AppCategoryId = 4845, ParentappCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5162 , ProtocolTitle="ABC: 3/28/20" },
    new AppCategoryDataModel() { AppCategoryId = 4845, ParentappCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },
    new AppCategoryDataModel() { AppCategoryId = 4845, ParentappCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5165 , ProtocolTitle="ABC: section", },
    new AppCategoryDataModel() { AppCategoryId = 4845, ParentappCategoryId = null, AppCategoryName = "ItemHostpital", ProtocolId =5192 , ProtocolTitle="ABC: 3/31/20", },
    new AppCategoryDataModel() { AppCategoryId = 4846, ParentappCategoryId = null, AppCategoryName = "Contact information", ProtocolId = null, ProtocolTitle="", },
    new AppCategoryDataModel() { AppCategoryId = 4846, ParentappCategoryId = null, AppCategoryName = "Contact information", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation", },
    new AppCategoryDataModel() { AppCategoryId = 4852, ParentappCategoryId = null, AppCategoryName = "UP", ProtocolId =null , ProtocolTitle="", },
    new AppCategoryDataModel() { AppCategoryId = 4852, ParentappCategoryId = null, AppCategoryName = "UP", ProtocolId = 5164, ProtocolTitle="ABC: Evaluation", },
    new AppCategoryDataModel() { AppCategoryId = 5023, ParentappCategoryId = null, AppCategoryName = "Call survival guide", ProtocolId = null, ProtocolTitle="" },
    new AppCategoryDataModel() { AppCategoryId = 5023, ParentappCategoryId = null, AppCategoryName = "Call survival guides", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },
    new AppCategoryDataModel() { AppCategoryId = 5085, ParentappCategoryId = null, AppCategoryName = "OE", ProtocolId =null, ProtocolTitle="" },
    new AppCategoryDataModel() { AppCategoryId = 5085, ParentappCategoryId = null, AppCategoryName = "OE", ProtocolId =5164 , ProtocolTitle="ABC: Evaluation" },

   new AppCategoryDataModel() { AppCategoryId = 5099, ParentappCategoryId = null, AppCategoryName = "OEM", ProtocolId =null , ProtocolTitle=null },

    new AppCategoryDataModel() { AppCategoryId = 5334, ParentappCategoryId = 5085, AppCategoryName = "mmkk update", ProtocolId =null , ProtocolTitle= null },
    new AppCategoryDataModel() { AppCategoryId = 5336, ParentappCategoryId = 5085, AppCategoryName = "xdgdrg", ProtocolId =null , ProtocolTitle=null },
    new AppCategoryDataModel() { AppCategoryId = 5348, ParentappCategoryId = 5023, AppCategoryName = "test", ProtocolId =null , ProtocolTitle=null },
    new AppCategoryDataModel() { AppCategoryId = 5341, ParentappCategoryId = 5023, AppCategoryName = "New Category Level-1", ProtocolId =null , ProtocolTitle= null },

    new AppCategoryDataModel() { AppCategoryId = 5349, ParentappCategoryId = 5341, AppCategoryName = "New Category Level-2", ProtocolId =null , ProtocolTitle= null },

    new AppCategoryDataModel() { AppCategoryId = 5352, ParentappCategoryId = 5348, AppCategoryName = "New category3", ProtocolId =null , ProtocolTitle= null },



}.OrderBy(ap => ap.AppCategoryName);

AppCategoryDataModel

public class AppCategoryDataModel
{
    public int AppCategoryId { get; set; }
    public int? ParentappCategoryId { get; set; }
    public string AppCategoryName { get; set; }
    public int? ProtocolId { get; set; }
    public string ProtocolTitle { get; set; }
}

Dictionary<int, FirstLevelCategory> dictCategories = new Dictionary<int, FirstLevelCategory>();

foreach (AppCategoryDataModel category in appCategoryList)
{
    if (!dictCategories.ContainsKey(category.AppCategoryId))
    {
        dictCategories.Add(category.AppCategoryId, new FirstLevelCategory()
        {
            AppCategoryId = category.AppCategoryId,
            AppCategoryName = category.AppCategoryName,
            AppCategoryProtocolData = category.ProtocolId != null ?

            new List<ProtocolDetails>() {
                new ProtocolDetails()
                {
                    ProtocolId = (int)category.ProtocolId,
                    ProtocolTitle = category.ProtocolTitle
                }
            } : new List<ProtocolDetails>(),

            SubCategory = category.ParentappCategoryId != null
            ? GetSubCategoryList(appCategoryList, category.AppCategoryId)
            : new List<SecondLevelCategory>()
        });
    }
    else
    {
        if (category.ProtocolId != null)
            dictCategories[category.AppCategoryId].AppCategoryProtocolData.Add(new ProtocolDetails()
            {
                ProtocolId = (int)category.ProtocolId,
                ProtocolTitle = category.ProtocolTitle
            });
    }
}
foreach (var key in dictCategories.Keys.ToList())
{
    dictCategories[key].CategoryProtocolCount = dictCategories[key].AppCategoryProtocolData.Count();
}

一级类别

public class FirstLevelCategory
{
    public int AppCategoryId { get; set; }
    public string AppCategoryName { get; set; }
    public bool IsExpand { get; set; }
    public bool IsExpandAll { get; set; }
    public bool IsCategoryHierarchyExpanded { get; set; }
    //count of AppCategoryProtocolData 
    public int CategoryProtocolCount { get; set; }
    public List<SecondLevelCategory> SubCategory { get; set; }
    public List<ProtocolDetails> AppCategoryProtocolData { get; set; }
}
public class ProtocolDetails
{
    public int ProtocolId { get; set; }
    public string ProtocolTitle { get; set; }
}

我的问题是 ParentappCategoryId != null 应该作为子类别出现的项目,但它也已添加到第一级类别中。我无法正确过滤。

我应该如何防止第一个添加具有 ParentAppCategory 的项目。

二级类别

public class SecondLevelCategory
{
    public int AppCategoryId { get; set; }
    public string AppCategoryName { get; set; }
    public bool? ToggleSubCategory { get; set; }
    public bool IsExpand { get; set; }
    public int subcategoryProtocolCount { get; set; }

    public IEnumerable<ProtocolDetails> SubCategoryProtocolData { get; set; }
    public List<ThirdLevelCategory> ThirdLevelCategory { get; set; }
}

三级类别

 public class ThirdLevelCategory
 {
    public int AppCategoryId { get; set; }
    public string AppCategoryName { get; set; }
    public bool? ToggleThirdLevelCategory { get; set; }
    public int? ThirdLevelCategoryProtocolCount { get; set; }
    public IEnumerable<ProtocolDetails> ThirdLevelCategoryProtocolData { get; set; }
 }

预期结果:

   ItemResearch
        ABC: Evaluation
    ItemHostpital
        ABC: 3/28/20
        ABC: Evaluation
        ABC: section
        ABC: 3/31/20
    Contact information
        ABC: Evaluation
    UP
        ABC: Evaluation
    OE
        ABC: Evaluation
            mmkk update --subcategory
            xdgdrg      --subcategory
    Call survival guides
        ABC: Evaluation --details
            test  --subcategory
                New category3 --thirdcategory
            New Category Level-1 --subcategory
                New Category Level-2 -- thirdcategory
 

My problem here is the item where ParentappCategoryId != null should come as a sub-category, but that has also been added in the first level category. I am not able to filter that properly.

我将其解释为 我只想要在我的字典的第一级中带有 ParentappCategoryId == null 的项目

如果是这种情况,应该可以通过过滤应用程序类别列表 来解决,然后 迭代它以将 first-level 项添加到您的字典中。

这是一个如何使用 System.Linq 命名空间中的 .Where() 实现的示例:

替换

foreach (AppCategoryDataModel category in appCategoryList)

//using System.Linq;

var firstLevelItems = appCategoryList.Where(app => app.ParentappCategoryId == null);

foreach (AppCategoryDataModel category in firstLevelItems)

注意:不需要单独的变量;我主要考虑使用它来提高可读性。

你不妨这样实现:

//using System.Linq;

foreach (AppCategoryDataModel category in appCategoryList.Where(app => app.ParentappCategoryId == null))

此外 -- 我不确定这部分是否会给您带来问题,但我觉得逻辑很奇怪:

SubCategory = category.ParentappCategoryId != null
    ? GetSubCategoryList(appCategoryList, category.AppCategoryId)
    : new List<SecondLevelCategory>()

我将代码解释为:

Populate category's SubCategory only if category has a parent

对我来说,考虑到 的 first-level 项没有 parent 的情况,这似乎意味着 none 的 first-level 项目应该有任何子类别。我觉得这是自相矛盾的。如有不妥请指正

如果我是对的,我建议实施 GetSubCategoryList() 以便 returns 如果 appCategoryList 中的 none 项具有 ParentappCategoryId == category.AppCategoryId.

如果你有,你可以简单地选择

SubCategory = GetSubCategoryList(appCategoryList, category.AppCategoryId)

更新:可能实施 GetSubCategoryList (GetSubCategories)

您在评论中提到,您当前的 GetSubCategoryList(和 GetThirdLevelCategoryList)实现几乎重复了主 foreach 循环的实现。

根据我的理解,这表明 classes FirstLevelCategorySecondLevelCategory(以及 ThirdLevelCategory)可以由单个 class 代替: AppCategory.

public class AppCategory
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ProtocolCount { get; set; }
    public List<AppCategory> SubCategories { get; set; }
    public List<ProtocolDetails> ProtocolData { get; set; }
}

此外,填充 AppCategoryProtocolData 的逻辑可以通过对共享 (AppCategory)Id 的所有应用类别进行分组并基于该分组创建 ProtocolDetails 列表来简化。

从这里开始,我们可以利用递归来获取每个类别的子类别。

private static List<AppCategory> GetSubCategories(
    List<AppCategoryDataModel> appCategories,
    int? parentAppCategoryId)
{
    // return empty list if no sub categories exist
    if (!appCategories.Any(ac => ac.ParentAppCategoryId == parentAppCategoryId))
    {
        return new();
    }
    
    List<AppCategory> subCategories = appCategories
        .Where(ac => ac.ParentAppCategoryId == parentAppCategoryId)
        // Simplify the logic of populating the ProtocolData content
        .GroupBy(ac => ac.AppCategoryId)
        .Select(gr => new AppCategory
            {
                Id = gr.Key,
                Name = gr.First().AppCategoryName,
                ProtocolData = gr
                    .Where(ac => ac.ProtocolId != null)
                    .Select(ac => new ProtocolDetails
                        {
                            Id = ac.ProtocolId.Value,
                            Title = ac.ProtocolTitle 
                        })
                    .ToList()
            })
        .ToList();
    
    foreach (var subCat in subCategories)
    {
        // Make recursive method call to populate _this_ category's sub categories
        subCat.SubCategories = GetSubCategories(appCategories, subCat.Id);
        subCat.ProtocolCount = subCat.ProtocolData.Count;
    }
    
    return subCategories;
}

事实证明,您字典中的所有 first-level 项实际上都可以被视为 具有 [=39= 的 (non-existing) 类别的子类别]。我们可以通过使用 GetSubCategories.

的实现找到我们的 first-level 项目来利用这一观察结果

主代码块可以缩减为:

Dictionary<int, AppCategory> dictCategories = new();

var firstLevelCategories = GetSubCategories(appCategoryList, null);

foreach (var category in firstLevelCategories)
{
    dictCategories.Add(category.Id, category);
}

使用您的示例输入数据生成的层次结构如下所示:

Call survival guide
        ABC: Evaluation
                New Category Level-1
                        New Category Level-2
                test
                        New category3
Contact information
        ABC: Evaluation
ItemHostpital
        ABC: 3/28/20
        ABC: Evaluation
        ABC: section
        ABC: 3/31/20
ItemResearch
        ABC: Evaluation
OE
        ABC: Evaluation
                mmkk update
                xdgdrg
OEM
UP
        ABC: Evaluation

请注意,此结果包括 OEM,但未包含在您的预期结果 中。如果您只想在字典中包含 first-level 个包含 ProtocolData 的项目,您可以例如筛选如下:

foreach (var category in firstLevelCategories.Where(c => c.ProtocolCount > 0))
{
    dictCategories.Add(category.Id, category);
}

示例 fiddle here.