简体   繁体   English

使用 Select() 从条件为真的列表中获取值

[英]Get a value from a list where a condition is true using Select()

I have a JSON array where I need to get the CustomerId value from property where the CustomerId property exits for that section, I'm trying below to loop through the categories and skip the one that has no CustomerId property down its properties tree我有一个 JSON 数组,我需要从该部分的 CustomerId 属性存在的属性中获取 CustomerId 值,我在下面尝试遍历类别并跳过其属性树下没有 CustomerId 属性的类别

var customerId = "";
    foreach (var category in JObject.Parse(someData)?["categories"])
            {
                val = category?["sections"].FirstOrDefault()
                ?["areas"]?.FirstOrDefault()
                ?["components"]?.
                ?["variables"]?.FirstOrDefault()
                ?["properties"]
                ?["customerId"]?.ToString();

                if (val == null)
                    continue;
                else
                {
                    customerId = val;
                    break;
                }

            }

Problem is this looks inefficient (less readable) in the sense that I imagine there is a nice .Select that can be used to get the same result without going forEach element and check if the property is null.问题是这看起来效率低下(可读性较差),因为我想有一个很好的.Select可以用来获得相同的结果而无需 forEach 元素并检查属性是否为 null。

Please not this is not an issue I have, this is working, I'd only like to do this in a more readable way using Select instead of ForEach .请注意,这不是我遇到的问题,这是有效的,我只想使用Select而不是ForEach以更具可读性的方式执行此操作。

Sample JSON Data样本 JSON 数据

 {
      "categories": [
        {
          "identifier": "cat1",
          "sections": [
            {
              "identifier": "030615e9-67f9-43ca-a06e-194e7afadccb",
              "properties": {},
              "areas": [
                {
                  "identifier": "1206f27b-d354-4bfa-9b5e-1fe6b4f7cc83",
                  "componenets": [
                    {
                      "identifier": "49e4550f-8001-4d32-b796-a7ad4423e118",
                      "type": "Product",
                      "variables": [
                        {
                          "identifier": "0d260417-fa6d-492b-85f1-dc2565bc4805",
                          "properties": {
                        
                            "description": ""
                            
                          }
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "identifier": "cat2",
          "sections": [
            {
              "identifier": "00b5bfa6-f482-47c2-bdd7-aaac273b7772",
              "properties": {},
              "areas": [
                {
                  "identifier": "1ca9d051-5ec0-45af-84bc-561cd7620efa",
                  "componenets": [
                    {
                      "identifier": "c73b1e52-3acd-4020-8fc5-adfef7d633b4",
                      "type": "Customer",
                      "variables": [
                        {
                          "identifier": "0064e872-5c7f-4ec7-a2d6-e8b35b94bd1d",
                          "properties": {
                            "customerId": { "Text":"MainId",
"Value":"A12123"
}
                          }
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }

An alternative approach is to use .SelectTokens from the JSON.NET library (which it appears you are using).另一种方法是使用.SelectTokens库中的 .SelectTokens (您正在使用它)。 Assuming parsedJson is your parsed root object as a JObject :假设parsedJson是您解析的根 object 作为JObject

var customerId = parsedJson.SelectTokens("$.categories..sections..areas..componenets[?(@.type == 'Customer')]..variables..properties.customerId.Value")
    .FirstOrDefault()?
    .ToString();

This essentially finds the first entry where a component has a type "Customer", and a property "customerId" and returns that customerId as a string.这实际上找到了第一个条目,其中组件具有类型“Customer”和属性“customerId”,并将该 customerId 作为字符串返回。

Strictly speaking you don't need the query on type ( [?(@.type == 'Customer')] ) but I got the impression that's what you were going for.严格来说,您不需要查询类型 ( [?(@.type == 'Customer')] ),但我觉得这就是您想要的。 Without it the query would look like this:没有它,查询将如下所示:

"$.categories..sections..areas..componenets..variables..properties.customerId.Value"

See more about SelectTokens in the docs here .此处的文档中查看有关SelectTokens的更多信息。

If you want to use the same logic as in you question, the code below is what you can use.如果您想使用与您提出的问题相同的逻辑,您可以使用下面的代码。

First you iterate over all the categories where you select the customerId field from.首先,您遍历select customerId字段所在的所有categories This will result in a list of customerIds where some are null and some might have a value.这将生成一个 customerId 列表,其中有些是null ,有些可能有值。

The next SingleOrDefault takes the first item from that list which does have a value.下一个SingleOrDefault从该列表中获取第一个确实有值的项目。 This will be your string customerId .这将是您的string customerId

Note: When there are no customerId's in your json, the customerId will be null .注意:当您的 json 中没有 customerId 时, customerId将为null If you want to throw an exception instead of working with null, you can use First() instead of FirstOrDefault .如果您想抛出异常而不是使用 null,您可以使用First()而不是FirstOrDefault

var customerId = JObject.Parse(someData)?["categories"]
                .Select(category => category?["sections"].FirstOrDefault()
                    ?["areas"]?.FirstOrDefault()?["components"]
                    ?["variables"]?.FirstOrDefault()
                    ?["properties"]
                    ?["customerId"]?.ToString())
                .SingleoOrDefault(customerId => customerId != null);

I have an optimized version:我有一个优化版本:

var pJson = JObject.Parse(someData);
JToken? customerToken = pJson.SelectToken($"$..customerId");
var customerId = customerToken?.ToString();

I would first parse the JSON to list of objects and the use the Linq to fetch the list of CusomerIds where it is not null.我首先将 JSON 解析为对象列表,然后使用 Linq 获取不是 null 的 CusomerIds 列表。

List<T> arrayItems = jsonBuidler?["categories"].ReadFromJson<List<T>>();
List<string> customerIds = arrayItems
   .Where(_ => CustomerId != null)
   .Select(_ => _.CustomerId);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM