如果有人能够有效地解决这个问题,我很好奇。我目前有以下对象。
Dictionary<int, Dictionary<double, CustomStruct>>
struct CustomStruct
{
double value1;
double value2;
...
}
鉴于我知道我想要访问的'int',我需要知道如何为具有最低(value1 + value2)之和的字典返回'double key'。任何帮助将不胜感激。我试图使用Linq,但任何方法都会受到赞赏。
答案 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;