如何使用 linq 查询具有嵌套列表的对象?

Posted

技术标签:

【中文标题】如何使用 linq 查询具有嵌套列表的对象?【英文标题】:How to query object with nested lists using linq? 【发布时间】:2019-01-28 18:51:39 【问题描述】:

我将来自第三方提供商的 JSON 反序列化为一个对象,并希望查询该对象以查找特定属性中的值。

我的问题是对象有一个属性(Parts),它的值是一个相同类型的列表。

public class RulePartModel

    public string isExistsUnder  get; set; 
    public int State  get; set;        
    public string Value  get; set; 
    public List<RulePartModel> Parts  get; set; 

当 Parts 属性可以有 6 或 7 个级别时,我如何查询此对象以查找特定值?

这是我收到的 JSON 示例:


  "isExistsUnder": null,
  "State": "",
  "Value": "CustomElements",
  "Parts": [
    
      "isExistsUnder": null,
      "State": 0,      
      "Value": "Rule 73",
      "Parts": [
        
          "isExistsUnder": null,
          "State": "",
          "Value": "For variable initializations",
          "Parts": [
            
              "isExistsUnder": null, 
              "State": "",             
              "Value": "cupis",
              "Parts": [
                
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText1",
                  "Parts": []
                ,
                
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText2",
                  "Parts": []
                ,
                
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText3",
                  "Parts": []
                
              ]
            
        
    

【问题讨论】:

部件的顶部是否只有一个元素,或者同一级别上可以有多个子部件? 同一层级可以有多个子部分。我更新了 json 示例以显示这一点。 【参考方案1】:

试试这个:

        static void Main(string[] args)
    
        var testobj = new RulePartModel();
        var results = FindParts(testobj, q => q.Value == "123");
        // results =>>> all objects with your condition
    
    static IEnumerable<RulePartModel> FindParts(RulePartModel obj, Func<RulePartModel, bool> predicate)
    
        if (predicate.Invoke(obj))
            yield return obj;
        foreach (var item in obj.Parts)
            foreach (var res in FindParts(item, predicate))
                yield return res;
    

或对非递归函数使用 @Parrish 建议:

        static IEnumerable<RulePartModel> FindParts(RulePartModel obj)
    
        var stack = new Stack<RulePartModel>();
        stack.Push(obj);
        while (stack.Count > 0)
        
            var current = stack.Pop();
            yield return current;
            foreach (var item in current.Parts)
                stack.Push(item);
        
    

用法示例:

var results = FindParts(testobj).Where(q => q.Value == "123");

【讨论】:

要添加到此答案,您也可以非递归地执行此操作。请参阅 Eric Lipperts 的回答:***.com/a/20335369/1316856 它是真的,但他说 6-7 级......所以我认为这个答案对他有用 OP 从未说明每个级别可以存在多少部分,因此示例可能要简单得多。 @AntonínLejsek。你在第二个例子中使用当前对象是对的,我忘了编辑那个循环。谢谢

以上是关于如何使用 linq 查询具有嵌套列表的对象?的主要内容,如果未能解决你的问题,请参考以下文章

linq 问题:查询嵌套集合

如何选择具有最低属性 linq 查询语法的对象

如何使用 Linq 在 Mongo C# 2.2 驱动程序中查询嵌套列表?

如何使用 LINQ 选择具有最小或最大属性值的对象

如何使用linq c#优化嵌套循环并从另一个列表中过滤

如何通过 orderBy 对嵌套的 Linq 对象进行排序