【问题标题】:How to query object with nested lists using linq?如何使用 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 示例以显示这一点。

标签: c# linq linq-to-objects


【解决方案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 的回答:stackoverflow.com/a/20335369/1316856
  • 它是真的,但他说 6-7 级......所以我认为这个答案对他有用
  • OP 从未说明每个级别可以存在多少部分,因此示例可能要简单得多。
  • @AntonínLejsek。你在第二个例子中使用当前对象是对的,我忘了编辑那个循环。谢谢
猜你喜欢
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多