筛选所有仅与输入字符串数组匹配或与任何数字匹配的Dictionary元素

时间:2019-01-04 12:12:53

标签: arrays linq dictionary join flatten

我有一个包含扁平键值对的Dictionary,并且有一个字符串数组。我只想获取字典元素,如果将其键拆分,则该字典元素应仅包含输入数组中指定的字符串或任何数字值。

目的是从展平的对象中读取属性的值列表。

示例字典:

Key: "Owner.0.Alias", Value: "Jo"
Key: "Owner.0.Name", Value: "John"
Key: "Owner.0.ReportsTo.Alias", Value: "Sam"
Key: "Owner.0.ReportsTo.Name", Value: "Samantha"    
Key: "Owner.1.Alias", Value: "Ma"
Key: "Owner.1.Name", Value: "Mary"
Key: "Owner.1.ReportsTo.Alias", Value: "Geo"
Key: "Owner.1.ReportsTo.Name", Value: "George"    
Key: "Manager.Alias", Value:"Ke"
Key: "Manager.Name", Value:"Ken"

输入数组-

string str = Owners.Alias;
var subStringArr = str.Split('.');

**Input array will have** : [0]: Owners, [1]:Alias

我想从上面的列表中过滤所有包含关键字“所有者” /“别名” /“数字”的词典元素。

**Expected output: **
Key: Owner.0.Alias, Value: Jo
Key: Owner.1.Alias, Value: Ma

请注意:词典键的层次结构级别可以很长。级别未知。

我尝试了几种使用join / intercept / contains过滤字典的方法。我面临的问题是,过滤后的字典还将在输入字符串数组之后还有一些其他关键字(如reportsTo)。

1 个答案:

答案 0 :(得分:0)

您可以执行以下操作。我将查询分为子查询以提高可读性。

var intial = dictionary.Keys.Select(c=> c.Split('.'));
var intermediate = intial.Where(x=>x
                            .Except(subStringArr)
                            .All(c=>Regex.IsMatch(c, @"^\d+$")));

var result =  intermediate.Select(x=> new KeyValuePair<string,string>(string.Join(".",x), dictionary[string.Join(".",x)]))
                        .ToDictionary(x=>x.Key, y=>y.Value);

输入

var dictionary = new Dictionary<string,string>{
["Owner.0.Alias"] = "Jo",
["Owner.0.Name"] = "John",
["Owner.0.ReportsTo.Alias"] = "Sam",
["Owner.0.ReportsTo.Name"] = "Samantha",
["Owner.1.Alias"] = "Ma",
["Owner.1.Name"] = "Mary",
["Owner.1.ReportsTo.Alias"] = "Geo",
["Owner.1.ReportsTo.Name"] = "George",
["Manager.Alias"] = "Ke",
["Manager.Name"] = "Ken",
};

string str = "Owner.Alias";
var subStringArr = str.Split('.');

您将得到的输出为

Key: Owner.0.Alias, Value: Jo
Key: Owner.1.Alias, Value: Ma

总体思路:

  1. 使用“。”分割键。进入数组
  2. 确保subStringArray是步骤1中数组的子集
  3. 确保在步骤2中成功子集匹配的所有剩余元素都是数字
  4. 形成最终结果

更新(基于评论)

为确保即使输入数组大于字典键长(例如“ Persona.Requestor.Owner.ReportsTo.Name”),也能获得结果,您可以将中间查询更改为

var intermediate = intial.Where(x=>  (subStringArr.Count() > x.Count()?
                                            subStringArr.Except(x)
                                           :x.Except(subStringArr))
                            .All(c=>Regex.IsMatch(c, @"^\d+$")));

这将有助于将键解析为“ Persona.0.Requestor.0.Owner.0.ReportsTo.Name”。