4

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

Dictionary<int, Dictionary<double, CustomStruct>>

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

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

4

5 回答 5

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

使用来自令人敬畏的MoreLINQ项目的MinBy 扩展方法。

于 2012-05-02T20:52:01.147 回答
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()/的组合Last()来获取它。

于 2012-05-02T21:37:45.860 回答
1

ADictionary<TKey,TValue>也是一个序列KeyValuePair<TKey,TValue>。您可以选择值总和最少的 KeyValuePair 并获取其键。

使用纯 LINQ to Objects:

dict[someInt].OrderBy(item => item.Value.value1 + item.Value.value2)
             .FirstOrDefault()
             .Select(item => item.Key);
于 2012-05-02T21:38:50.533 回答
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 解决方案具有创新性,但需要重新计算与当前最佳匹配比较的每个项目的当前最佳匹配的总和,因为您在聚合调用之间携带的状态不足。

于 2012-05-02T22:22:57.343 回答
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;
于 2012-05-03T12:54:19.663 回答