【问题标题】:Query a Dictionary of Dictionaries?查询字典?
【发布时间】:2026-01-13 04:25:01
【问题描述】:

请您告诉我如何查询词典词典和/或列表词典?

private Dictionary<string, Dictionary<DateTime, double>> masterDict= new Dictionary<string, Dictionary<DateTime, double>>();

Private Dictionary<string, List<DateTime>> masterList= new Dictionary<string, List<DateTime>>();

我知道如果我执行以下操作,我会得到 masterDict 中包含的字典列表,但我不确定如何获取这些字典的值。

 foreach (var kvp in masterDictMethod())
        {
            Console.WriteLine("Key = {0}, Value = {1}",
                kvp.Key, kvp.Value);
        }

感谢收看 ;)

【问题讨论】:

    标签: c# .net linq list dictionary


    【解决方案1】:

    您询问了列表、字典和包含其他字典的字典。

    我最近有一个类似的话题,我想有一个可查询的字典(即允许将查询表达式作为 lambda 参数传递的扩展方法),您可以像这样使用:

    var result = myDictionary.QueryDictionary(w => myList.Any(a => a == w.Key));
    

    此代码行的目的是检查字典的任何键是否包含在 myList 中。

    所以我做的是这样,我写了如下扩展方法:

    // extension method using lambda parameters
    public static Dictionary<string, T> QueryDictionary<T>(
        this Dictionary<string, T> myDict, 
        Expression<Func<KeyValuePair<string,T>, bool>> fnLambda)
    {
        return myDict.AsQueryable().Where(fnLambda).ToDictionary(t => t.Key, t => t.Value);
    }
    

    它可以用于每个具有string 类型键和每个对象类型T 的项目的字典。

    现在您可以通过传递 lambda 表达式轻松编写查询,如下例所示:

    var list1 = new List<string>() { "a", "b" };
    var myDict = new Dictionary<string, object>();
    myDict.Add("a", "123"); myDict.Add("b", "456"); myDict.Add("c", "789"); 
    
    var result = myDict.QueryDictionary(w => list1.Any(a => a == w.Key));
    

    结果将包含项目 a 和 b,因为它们包含在 list1 中。

    你也可以查询dictionary of dictionaries,这里是LinqPadC#示例,但它也可以用作控制台应用程序(只需注释掉.Dump() 语句并将它们替换为 Console.WriteLine(...) 语句):

    void Main()
    {
        // *** Set up some data structures to be used later ***
        var list1 = new List<string>() { "a", "b", "d" }; // a list
        var myDict = new Dictionary<string, object>(); // the dictionary
        myDict.Add("a", "123"); myDict.Add("b", "456"); myDict.Add("c", "789"); 
    
        var myDict2 = new Dictionary<string, object>(); // 2nd dictionary
        myDict2.Add("a", "123"); myDict2.Add("b", "456"); myDict2.Add("c", "789"); 
    
        myDict.Add("d", myDict2); // add 2nd to first dictionary
    
        // *** 1. simple query on dictionary myDict ***
        var q1 = myDict.QueryDictionary(w => list1.Any(a => a == w.Key));
        q1.Dump();
    
        // *** 2. query dictionary of dictionary (q3 contains result) ***
        var q2 = 
          (Dictionary<string, object>)q1.QueryDictionary(w => w.Key.Equals("d")).First().Value; 
        var q3 = q2.QueryDictionary(w => w.Key.Equals("b"));
        q3.Dump();
    }
    
    // *** Extension method 'QueryDictionary' used in code above ***
    public static class Extensions
    {
        public static Dictionary<string, T> QueryDictionary<T>(
           this Dictionary<string, T> myDict, 
           Expression<Func<KeyValuePair<string, T>, bool>> fnLambda)
        {
            return myDict.AsQueryable().Where(fnLambda).ToDictionary(t => t.Key, t => t.Value);
        }
    }
    

    由于此方案使用泛型,您可以将任何 lambda 表达式作为搜索参数传递,因此非常灵活。

    【讨论】:

      【解决方案2】:

      这个是:

      var masterDictionary = new Dictionary<string, Dictionary<DateTime, double>>(); 
      
      var query =
        from kvp1 in masterDictionary
        from kvp2 in kvp1.Value
        select new {TheString = kvp1.Key, TheDate = kvp2.Key, TheDouble = kvp2.Value };
      
      foreach(var x in query)
      {
        Console.WriteLine("{0} {1} {2}", x.TheString, x.TheDate, x.TheDouble);
      }
      

      然后另一个是:

      var masterList= new Dictionary<string, List<DateTime>>(); 
      
      var query =
        from kvp in masterList
        from val in kvp.Value
        select new {TheString = kvp.Key, TheDate = val);
      
      foreach(var x in query)
      {
        Console.WriteLine("{0} {1}", x.TheString, x.TheDate);
      }
      

      【讨论】:

      • 你知道通过扩展方法而不是查询来做到这一点吗?
      • @MGG_Soft 是的,您正在寻找 Enumerable.SelectMany 的重载之一
      【解决方案3】:

      在你 foreach kvp.Value 是每个 masterDict 条目的内部字典,即 Dictionary&lt;DateTime, double&gt;

      因此,只需 foreach 也超过 kvp.Value,您将获得内部值。

      例如

      foreach (var kvp1 in masterDictMethod())
      {
         Console.WriteLine("Key = {0}, Inner Dict:", kvp1.Key);
         foreach (var kvp2 in kvp1.Value)
         {
            Console.WriteLine("Date = {0}, Double = {1}", kvp2.Key, kvp2.Value);
         }
      }
      

      【讨论】:

        【解决方案4】:
        foreach (var key in masterDict.Keys)
        {
            var nestedDict = masterDict[key];
        }
        

        【讨论】:

        • 最好这样做:foreach (var kv in masterDict) { /* work with kv.Value - the inner dict. */ }。这节省了内部查找(Dictionary&lt;K,V&gt; 实现了IEnumerable&lt;KeyValuePair&lt;K,V&gt;&gt;。)
        【解决方案5】:

        使用masterDict.Values

        【讨论】: