2012-05-02 64 views
4

我很好奇,如果有人有一个很好的方法来有效地解决这个问题。我目前有以下的对象。查询嵌套字典

Dictionary<int, Dictionary<double, CustomStruct>> 

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

既然我知道了“廉政”我要上网,我需要知道如何返回有(值1 +值2)的最低金额字典“双钥匙”。任何帮助将不胜感激。我试图使用Linq,但任何方法将不胜感激。

回答

4
var result = dict[someInt].MinBy(kvp => kvp.Value.value1 + kvp.Value.value2).Key; 

使用从真棒MoreLINQ项目MinBy Extension Method

+0

不贪,因为看起来像正是我需要,从MoreLINQ文档...但有另一种如何在不使用MoreLINQ项目的情况下实现这一目标? – TheButlerDidIt

+0

感谢所有帮助球员,发现太这种方式: **字典[someInt] .Aggregate((种子,O)=> { 变种V = seed.Value.value1 + seed.Value.value2 ; var k = o.Value.value1 + o.Value.value2; return v TheButlerDidIt

+0

@TheSelected:这实际上是做完全查询的一个很好的选择。把它作为答案。 :) –

1

只需使用普通的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 to得到最小的或最大的项目,你通常要做到这一点使用第i个GroupBy()OrderBy()First()/Last()组合来获得它。

1

A Dictionary<TKey,TValue>也是KeyValuePair<TKey,TValue>的序列。您可以选择具有最小和值的KeyValuePair并获取其密钥。

使用纯LINQ到对象:

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

这里的非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的解决方案具有创新性,但需要重新计算当前最匹配的每个项目的当前最佳匹配总和,因为在总计呼叫之间没有足够的状态。

0

感谢所有帮助家伙,发现过这种方式:

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;