字典值包含字符串数组中的任何一项

问题描述

我正在使用以下模型反序列化来自 api 端点的 JSON 响应

    public class APIModel
    { 
        public int Prop1 { get; set; }
        public int Prop2 { get; set; }
        public int Prop3 { get; set; }          
         
        public Dictionary<string,Dictionary<string,string>> DictMaster { get; set; }                      
    }
    

来自 API 的 JSON 就像

            [{
            -----------------
            "DictMaster": {
                "0": {
                    "0": "No","1": "94041"
                },"1": {
                    "0": "Date","1": "08 / 06 / 2020"
                },"2": {
                    "0": "sDate","1": "15 / 06 / 2020"
                },"3": {
                    "0": "ONo","1": "113003"
                }
            }
        },{ 
            -----------------
            "DictMaster": {
                "0": {
                    "0": " Net","1": "£ 212.40"
                },"1": {
                    "0": "Car","1": "£ 0.00"
                },"2": {
                    "0": "Amount","1": "£ 42.48"
                },"3": {
                    "0": " Total","1": "£ 254.88"
                }
            }
        },{
             -----------------
            "DictMaster": {
                "0": {
                    "0": "Qty col","1": "Ref col","2": "Description","3": "Unit","4": "Net"
                },"1": {
                    "0": "2","1": "4d05","2": " Ball -G -   Red","3": "8.85","4": "2140"
                }
            }
        }
    ]

这是反序列化和正常工作的代码

var models = JsonConvert.DeserializeObject<List<APIModel>>(json);
    
List<Dictionary<string,string>> 
    tablemodel = (from p in  models
                  from d in p.DictMaster
                  select d.Value).ToList();
    

该列表包含 10 个项目并且运行良好,这基本上是 JSON 响应中可用的所有 dictionary 项目的列表。我想对这个列表再应用一个过滤条件。我有一组搜索关键字,需要将字典值与搜索关键字进行比较。如果任何字典值包含搜索关键字的一部分,那么我必须选择该特定的“DictMaster”并将值从它们转换为 List<Dictionary<string,string>>

在这个给定的 JSON 中,“DictMaster”最后一个下的字典包含来自搜索关键字列表“Qty”和“Ref”的一些值,因此需要选择“DictMaster”的最后一个实例作为结果集

string[] search_keys = new string[] {"Qty","ref" };
List<Dictionary<string,string>> tablemodel = (from p in models
                                               from v in p.DictMaster
                                               where search_keys.Any(v.Value.ContainsValue)
                                               select v.Value).ToList();
                                                           

但这会返回 0 个项目。我希望这能返回 2 个项目

如何选择或过滤至少与搜索关键字列表匹配的字典?

根据答案部分和评论中的建议,我设法完成了如下查询以获得结果

string[] search_keys = new string[] {"qty","ref" };

var responseModel = (from p in models
                     from dict in p.DictMaster
                     from x in p.DictMaster.Values
                     from val in dict.Value
                     where search_keys.Any(d => val.Value.ToLower().Contains(d))
                     select x.Values).ToList();

解决方法

这是可行的,但您也需要小写的搜索值。目前,您还必须区分它。

        var search_keys = new string[] { "qty","ref" };
        var tablemodel = new List<Dictionary<string,string>>();

        foreach (var dict in models.SelectMany(model => model.DictMaster))
        {
            tablemodel.AddRange(from val in dict.Value where search_keys.Any(d => val.Value.ToLower().Contains(d)) select dict.Value);
        }

您可以使用哈希集来区分它们,但我猜这取决于您的 JSON 的大小:

        string[] search_keys = new string[] { "qty","ref" };
        var tablemodel = new HashSet<Dictionary<string,string>>();

        foreach (var dict in
            from model in models
            from dict in model.DictMaster
            from val in dict.Value
            where search_keys.Any(d => val.Value.ToLower().Contains(d))
            select dict)
        {
            tablemodel.Add(dict.Value);
        }
,

考虑您的 LINQ 查询:

from p in models
    from v in p.DictMaster
    where search_keys.All(v.Value.ContainsValue)
    select v.Value

根据您的模型,v.Value 将类似于:

 "3": {
          "0": " Total","1": "£ 254.88"
      }

这永远不会匹配您的搜索字符串。您的 LINQ 查询需要另一个级别:

from p in models
    from v in p.DictMaster
        from x in v.Value
        where search_keys.Any(x.Value.ContainsValue)
        select x.Value