简体   繁体   English

找不到Linq查询的相应运算符

[英]Can't find the appropriate operators for a Linq query

I need help building a Linq query. 我需要帮助构建Linq查询。 I have this dictionary : 我有这本字典:

var dict = new Dictionary<string, IDictionary<int, double>>  
{  
    { "one", new Dictionary<int, double>  
        {  
            { 1, 2.0 },  
            { 2, 3.0 }  
        }},  
    { "two", new Dictionary<int, double>  
        {  
            { 1, 3.0 },  
            { 2, 4.0 },  
            { 3, 5.0 }  
        }},  
    { "three", new Dictionary<int, double>  
        {  
            { 1, 4.0 },  
            { 2, 5.0}  
        }}  
    };  

I want to select all "string"/"int" tuples whose associated value is 3.0. 我想选择其关联值为3.0的所有“string”/“int”元组。 With Foreach loops, it looks like : 使用Foreach循环,它看起来像:

var res = new Dictionary<string, int>();
foreach (var elem in dict.Select (d => new { S = d.Key, I = d.Value }))
{
    foreach (var val in elem.I)
    {
        if (val.Value == 3.0)
        {
            res.Add(elem.S, val.Key);
        }
    }
}

I'm trying to do the same with a single Linq query but with no success (I don't know how to "join" the key with the value from a subquery). 我正在尝试使用单个Linq查询执行相同但没有成功(我不知道如何使用子查询中的值“加入”键)。 How would you do this? 你会怎么做?

Thank you in advance! 先感谢您!

This would do the trick: 这样可以解决问题:

var  res = dict
        .Where(outer => outer.Value.Any(inner => inner.Value == 3.0))
        .ToDictionary(outer => outer.Key, outer => outer.Value.First(x=>x.Value == 3.0).Key);

or to make the code a bit more generic: 或者使代码更通用:

var predicate = new Func<KeyValuePair<int, double>, bool>(inner => inner.Value == 3.0); 
var  res = dict
        .Where(outer => outer.Value.Any(inner => predicate(inner)))
        .ToDictionary(outer => outer.Key, outer => outer.Value.First(inner => predicate(inner)).Key);

Here's another butt-ugly way to do it: 这是另一种愚蠢的方式:

var results = from key1 in dict.Keys
              let valueDict = dict[key1]
              from key2 in valueDict.Keys
              where valueDict[key2] == 3d
              select new { Key1 = key1, Key2 = key2 };

You could do it this way: 你可以这样做:

var result = dict
    // flatten to 3-value tuple
    .SelectMany(kvp => kvp.Value
        .Select(kvp2 => new // anonymous object
        {
            OuterKey = kvp.Key, // e.g. "one"
            InnerKey = kvp2.Key, // e.g. 1
            InnerValue = kvp2.Value // e.g. 2.0
        })
    ).Where(o => o.InnerValue == 3.0) // limit to the 3.0 value
    .ToDictionary(o => o.OuterKey, o => o.InnerKey)
    ;

The SelectMany flattens the dictionary of dictionaries into a structure that looks like this: SelectMany将字典字典展平为一个如下所示的结构:

{ OuterKey = "one", InnerKey = 1, InnerValue = 2.0 },
{ OuterKey = "one", InnerKey = 2, InnerValue = 3.0 },
{ OuterKey = "two", InnerKey = 1, InnerValue = 3.0 },
{ OuterKey = "two", InnerKey = 2, InnerValue = 4.0 },
{ OuterKey = "two", InnerKey = 3, InnerValue = 5.0 },
{ OuterKey = "three", InnerKey = 1, InnerValue = 4.0 },
{ OuterKey = "three", InnerKey = 2, InnerValue = 5.0 }

The Where() limits it down to just the objects with InnerValue = 3.0: Where()将其限制为InnerValue = 3.0的对象:

{ OuterKey = "one", InnerKey = 2, InnerValue = 3.0 },
{ OuterKey = "two", InnerKey = 1, InnerValue = 3.0 }

The ToDictionary() looks like this: ToDictionary()看起来像这样:

{ "one", 2 },
{ "two", 1 }

If it's possible for there to be more than a single 3.0 under the same outer key, then you can use ToLookup() instead of ToDictionary(). 如果在同一个外键下可能有多个3.0,则可以使用ToLookup()而不是ToDictionary()。

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

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