我发现了C#
提供的工具来处理集合。
假设我有元素列表,我想检索最满足属性的那个。基本上是elements.Max(predicate)
,除了我对最佳元素的索引感兴趣。我想要索引而不是元素本身的原因可能是没有这样的元素,并且类型是不可为空的。
此时我有以下代码,它仍然看起来很混乱,并且会对属性进行两次评估。
List<foo> elements;
private int getBest(object x)
{
var indices = Enumerable.Range(0, elements.Count);
return indices.Aggregate(-1, (best, next) =>
(-1 == best || eval(x, elements[next]) > eval(x, elements[best])) ? next : best);
}
如何让这段代码变得更好?
附录:为了清晰起见,我没有将其放在代码中,但如果eval()
低于某个阈值,则该元素将被丢弃。
答案 0 :(得分:1)
使用LINQ这样做很有趣,但没有LINQ这样做会使它更直观:
int bestIndex = -1;
int bestResult = -1;
for(int i = 0; i < elements.Count; ++i)
{
int currentResult = eval(x, elements[i]);
if (currentResult > bestResult)
{
bestResult = currentResult;
bestIndex = i;
}
}
答案 1 :(得分:1)
我建议将Select
与Aggregate
LINQ扩展方法结合使用。使用Select
方法,您可以创建一个匿名类型,其中包含集合中每个项目的index
和value
。然后使用LINQ Aggregate
方法,您可以缩小具有最大值的项目。我认为有些人应该这样做:
private int GetIndexOfHighestValue(IEnumerable<int> list)
{
return list.Select((i, v) => new { Index = i, Value = v })
.Aggregate((a, b) => (a.Value > b.Value) ? a : b)
.Index;
}
答案 2 :(得分:0)
像这样的东西可以起作用:
// OOPS: This won't work because Max is defined the way it is. Always bugged me...
var result = elements.Select((e, i) => new {Element = e, Index = i}).Max(x => x.Element).Select(x => x.Index);
哦,老鼠。对。这不行。所以:让我们全力以赴:Aggregate
。我们走了:
var elements = new List<int>{1, 7, 2, 5};
var result = elements.Select((e, i) => new {Element = e, Index = i})
.Aggregate(
new { Element = elements.First(), Index = -1}, // gotta start somewhere and Element is non-nullable according to OP
(max, next) => (max.Element > next.Element) && max.Index >= 0 ? max : next,
max => max.Index);
这导致1
。这有帮助吗?