查询嵌套字典

时间:2012-05-02 20:48:02

标签: c# linq dictionary

如果有人能够有效地解决这个问题,我很好奇。我目前有以下对象。

Dictionary<int, Dictionary<double, CustomStruct>>

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

鉴于我知道我想要访问的'int',我需要知道如何为具有最低(value1 + value2)之和的字典返回'double key'。任何帮助将不胜感激。我试图使用Linq,但任何方法都会受到赞赏。

5 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分: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获取最小或最大项目时,通常必须使用GroupBy()OrderBy()First() / {{1}的组合来完成得到它。

答案 2 :(得分:1)

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

使用纯LINQ到对象:

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

答案 3 :(得分: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;
}

如果你想在不使用extern库的情况下使用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的解决方案是创新的,但需要重新计算当前最佳匹配的每个项目的当前最佳匹配的总和,因为在聚合调用之间没有足够的状态。

答案 4 :(得分: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;