LINQ查询嵌套字典,在C#中具有多个键值选择

时间:2020-03-03 12:17:08

标签: c# linq dictionary key-value

我正面临一个问题,无法找到任何合适的解决方案。我有一个嵌套的字典,其布局如下:

var dict = new Dictionary<int, Dictionary<string , dynamic>>()
{
 0 : {Name : "abc" , marks1 : 05 , Marks2 : 10 , marks3 : 39},
 1 : {Name : "efg" , marks1 : 20 , Marks2 : 30 , marks3 : 25},
 2 : {Name : "hig" , marks1 : 30 , Marks2 : 40 , marks3 : 33},
 3 : {Name : "xyz" , marks1 : 40 , Marks2 : 10 , marks3 : 50}
}

我正在尝试使用LINQ查询以获取其中id个查询中的true,但是我无法为查询选择两个或三个条件。对于一个键值,以下查询正常工作

    var query = from id in dict
                    from info in id.Value
                    where (info.Key == "marks1" && Convert.ToDouble(info.Value) > 10)
                    select id

但是当我尝试2或3条条件来获取行ID时,例如在其下无效。

    var query = from id in dict
                    from info in id.Value
                    where (info.Key == "marks1" && Convert.ToDouble(info.Value) > 10) 
                    && (info.Key == "marks2" && Convert.ToDouble(info.Value) > 20)
                    select id 

此外,如果我必须将值相互比较,例如marks1mark2的值应该更大。如何执行此类查询?尤其是当我不允许通过这样的键访问值时:

mark3

在LINQ中,它给我以下错误:

无法将[]的索引应用于'keyvaluepair类型的表达式< 字符串,动态>

4 个答案:

答案 0 :(得分:2)

我尝试了这个,并且奏效了

var result = dict.Where(x => x.Value.Any(y => y.Key == "marks1" && int.Parse(y.Value) > 10))
                 .Where(x => x.Value.Any(y => y.Key == "marks2" && int.Parse(y.Value) > 31));

答案 1 :(得分:2)

您可以使用

var result= dict.Where(x=>Convert.ToDouble(x.Value["marks1"])>10 
                       && Convert.ToDouble(x.Value["Marks2"])>20)
                .Select(x=>x.Key);

输出

1 
2

答案 2 :(得分:1)

外部来源:
dictKeyValuePairs的序列,其中Key是int,Value是内部Dictionary<string, dynamic>。因此,id是此KeyValuePairs序列中的一个元素:它是一个这样的KeyValuePair。

内部来源:
id.ValueDictionary<string, dynamic>,它是KeyValuepairs的字符串,其中每个Key是一个字符串,每个Value是一个动态变量。

您不希望内部字典中有所有KeyValuePair,而只希望其中一些:

where (info.Key == "marks1" && Convert.ToDouble(info.Value) > 10) 
   && (info.Key == "marks2" && Convert.ToDouble(info.Value) > 20)

如果我读过这篇文章,则只希望内部字典中具有等于“ marks1”和“ marks2”的字符串Key的KeyValuePair。确定要吗?在我看来,结果将是一个空集合。

A,您没有写您的要求,所以我不得不猜测。

我认为,您的外部词典中的每个KeyValuePair元素都需要键(这是您的外部词典中的int),以及内部词典中所有具有以下条件的所有KeyValuePair序列

  • 任一(键==“ marks1” AND Convert.ToDouble(info.Value)> 10)
  • OR(键==“ marks2” AND Convert.ToDouble(info.Value)> 20)

我对查询语法不是很熟悉,所以我将改用methodSyntax。

Dictionary<int, Dictionary<string, dynamic>> dict = ...;
var result = dict.Select( outerKeyValuePair => new
{
    Key = outerKeyValuePair.Key,
    Values = outerKeyValuePair.Value
        // I don't want all values from the inner dictionary
        // I only want those where (Key == "marks1" and ...) OR (Key == "marks2 and ...)
        .Where(innerKeyValuePair => 
              (innerKeyValuePair.Key == "marks1" && Convert.ToDouble(innerKeyValuePair.Value) > 10)
              ||
              (innerKeyValuePair.Key == "marks2" && Convert.ToDouble(innerKeyValuePair.Value) > 20))

         // from the remaining inner KeyValuePairs select the properties that you want
         .Select(innerKeyValuePair => new
         {
              Name = innerKeyValuePair.Key,
              Value = innerKeyValuePair.Value,
         })
         .ToList(),
    });

换句话说:您的外部字典是外部KeyValuePairs的序列。从该序列中的每个keyValuePair中,创建一个新对象,其中包含两个属性:KeyValues

Key属性是KeyValuepair中的键。

Values属性是一个列表。它包含由内部词典构成的对象,这些对象属于外部词典中Key的值。

此内部字典也是KeyValuePairs的序列。我只保留其中一些内部KeyValuePair,即仅在以下位置:

  • 键等于“ marks1”且Convert.ToDouble(value)大于10
  • OR:键等于“ marks2 AND Convert.ToDouble(value)大于20

从内部词典中其余的每个KeyValuePair中,我创建一个包含属性NameValue的新对象。

Name是内部KeyValuePair的键(等于“ marks1”或“ marks2”) Value是此内部KeyValuePair的值。

当然,如果需要其他属性,可以选择它们而不是我选择的属性:

.Select(innerKeyValuePair => new
{
    Marks = innerKeyValuePair.Key,                     // equals "marks1" OR "marks2"
    Value = Convert.ToDouble(innerKeyValuePair.Value),
})
.ToList(),

答案 3 :(得分:1)

您可以像这样平铺字典:

    dict.Select(item=> new { 
                            Id = item.Key, 
                            Name = item.Value["Name"],
                            marks1 = Convert.ToDouble(item.Value["marks1"]), 
                            marks2 = Convert.ToDouble(item.Value["marks2"]),
                            marks3 = Convert.ToDouble(item.Value["marks3"]) 
                          }
                 )
           .Where(item=> item.marks1 > 10 && 
                         item.marks2 > 20)
           .Select(item=> item.Id)

此查询返回记录的ID。如果您需要所选数据的完整记录,可以使用以下方法:

    dict.Select(item=> new { 
                            item = item, 
                            Name = item.Value["Name"],
                            marks1 = Convert.ToDouble(item.Value["marks1"]), 
                            marks2 = Convert.ToDouble(item.Value["marks2"]),
                            marks3 = Convert.ToDouble(item.Value["marks3"]) 
                          }
                 )
           .Where(item=> item.marks1 > 10 && 
                         item.marks2 > 20)
           .Select(item=> item)