2

我正在发现C#用于处理集合的工具。

假设我有一个元素列表,并且我想检索最满足某个属性的元素。基本上是一个elements.Max(predicate),除了我对最佳元素的索引感兴趣。我想要索引而不是元素本身的原因是可能没有这样的元素,并且类型不可为空。

编写一个这样做的函数是微不足道的,但我有兴趣使用 C# 提供的工具的表现力来获得一个简洁清晰最优( O(n) ) 的解决方案。

在这一点上,我有以下代码,它看起来仍然很混乱,并且对属性进行了两次评估。

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()低于某个阈值,则丢弃该元素。

4

3 回答 3

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;
    }
}
于 2012-05-24T08:06:50.690 回答
1

我建议将LINQ 扩展方法SelectAggregateLINQ 扩展方法结合使用。使用该Select方法,您可以创建一个匿名类型,其中包含集合中每个项目的index和。value然后使用 LINQAggregate方法,您可以缩小具有最大价值的项目。我认为这样的一些应该有效:

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;
}
于 2012-05-24T08:09:39.643 回答
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. 那有帮助吗?

于 2012-05-24T07:54:22.540 回答