【问题标题】:Query Nested Dictionary查询嵌套字典
【发布时间】:2012-05-02 20:48:02
【问题描述】:

我很好奇是否有人有有效解决此问题的好方法。我目前有以下对象。

Dictionary<int, Dictionary<double, CustomStruct>>

struct CustomStruct
{
    double value1;
    double value2;
    ...
}

鉴于我知道我想要访问的“int”,我需要知道如何为 (value1 + value2) 之和最小的字典返回“双键”。任何帮助将不胜感激。我正在尝试使用 Linq,但任何方法都会受到赞赏。

【问题讨论】:

    标签: c# linq dictionary


    【解决方案1】:
    var result = dict[someInt].MinBy(kvp => kvp.Value.value1 + kvp.Value.value2).Key;
    

    使用来自很棒的MoreLINQ 项目的MinBy Extension Method

    【讨论】:

    • 不要贪心,因为这看起来正是我所需要的,从 MoreLINQ 的文档中......但是有没有其他方法可以在不使用 MoreLINQ 项目的情况下有效地做到这一点?
    • 感谢所有帮助人员,也发现了这种方式: dict[someInt].Aggregate( (seed, o) => { var v = seed.Value.value1 + seed. Value.value2; var k = o.Value.value1+ o.Value.value2; return v
    • @TheSelected:这实际上是一个很好的替代完整查询的方法。把它作为答案。 :)
    【解决方案2】:

    只使用普通的 LINQ:

    Dictionary<int, Dictionary<double, CustomStruct>> dict = ...;
    int id = ...;
    
    var minimum =
       (from kvp in dict[id]
        // group the keys (double) by their sums
        group kvp.Key by kvp.Value.value1 + kvp.Value.value2 into g
        orderby g.Key          // sort group keys (sums) in ascending order
        select g.First())      // select the first key (double) in the group
       .First();               // return first key in the sorted collection of keys
    

    当您想使用普通 LINQ 获取最小或最大项目时,通常必须使用 GroupBy()OrderBy()First()/Last() 的组合来获取它。

    【讨论】:

      【解决方案3】:

      Dictionary&lt;TKey,TValue&gt; 也是KeyValuePair&lt;TKey,TValue&gt; 的序列。您可以选择值总和最少的 KeyValuePair 并获取其键。

      使用纯 LINQ to Objects:

      dict[someInt].OrderBy(item => item.Value.value1 + item.Value.value2)
                   .FirstOrDefault()
                   .Select(item => item.Key);
      

      【讨论】:

        【解决方案4】:

        这是非 LINQ 方式。它并不比它的 LINQ 对应物短,但它更高效,因为它不像大多数 LINQ 解决方案那样进行排序,如果集合很大,这可能会变得很昂贵。

        dtb 的 MinBy 解决方案是一个不错的解决方案,但它需要一个外部库。我确实很喜欢 LINQ,但有时您应该提醒自己,带有一些局部变量的 foreach 循环不是过时的或错误的。

        CustomStruct Min(Dictionary<double, CustomStruct> input)
        {
            CustomStruct lret = default(CustomStruct);
            double lastSum = double.MaxValue;
        
            foreach (var kvp in input)
            {
                var other = kvp.Value;
                var newSum = other.value1 + other.value2;
                if (newSum < lastSum)
                {
                    lastSum = newSum;
                    lret = other;
                }
            }
            return lret;
        }
        

        如果您想使用 LINQ 方法而不使用外部库,您可以创建自己的 MinBy,如下所示:

        public static class Extensions
        {
            public static T MinBy<T>(this IEnumerable<T> coll, Func<T,double> criteria)
            {
                T lret = default(T);
                double last = double.MaxValue;
                foreach (var v in coll)
                {
                    var newLast = criteria(v);
                    if (newLast < last)
                    {
                        last = newLast;
                        lret = v;
                    }
                }
                return lret;
            }
        
        }
        

        它不如第一个高效,但它可以完成工作,并且比第一个更可重用和可组合。您的 Aggregate 解决方案具有创新性,但需要重新计算与当前最佳匹配比较的每个项目的当前最佳匹配的总和,因为您在聚合调用之间携带的状态不足。

        【讨论】:

          【解决方案5】:

          感谢大家的帮助,我也是这样发现的:

          dict[int].Aggregate(
                              (seed, o) =>
                                  {
                                      var v = seed.Value.TotalCut + seed.Value.TotalFill;
                                      var k = o.Value.TotalCut + o.Value.TotalFill;
                                      return v < k ? seed : o;
                                  }).Key;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-05
            相关资源
            最近更新 更多