查找最大值小于另一个值的项目

时间:2011-10-13 15:49:42

标签: c#

我有一个有两个双打的对象:

class SurveyData(){ double md; double tvd; }

我有一个已经按升序排序的值列表。我想找到并返回列表中对象的索引,其最大tvd值小于或等于double。我怎样才能有效地完成这项任务?

3 个答案:

答案 0 :(得分:3)

假设你有LINQ并且很高兴使用MoreLINQ中的TakeUntil,我怀疑你想要:

var maxCappedValue = values.TakeUntil(data => data.Tvd >= limit)
                           .LastOrDefault();

这将为您提供第一个实际值而不是 index ,但您可以随时执行:

var maxCappedPair = values.Select((value, index) => new { value, index })
                           .TakeUntil(pair => pair.value.Tvd >= limit)
                           .LastOrDefault();

表示索引/值对。在这两种情况下,如果所有值都高于限制,结果将为null。

当然,使用二进制搜索会更有效 - 但也会稍微复杂一些。您可以使用限制TVD创建“虚拟”值,然后使用List<T>.BinarySearch(dummy, comparer),其中comparer将是IComparer<SurveyData>的实现,由TVD进行比较。然后,您需要检查返回值是非负数(找到完全匹配)还是负数(未找到完全匹配,返回值是插入的位置的补充)。

复杂度的差异在于简单扫描的O(n)或二进制搜索的O(log n)。在不知道列表有多大(或性能有多重要)的情况下,很难建议二进制搜索的额外实现复杂性是否值得。

答案 1 :(得分:1)

首先按小于或等于过滤器值(Where)的对象进行过滤,然后选择这些对象的最大值。

由于它已经按升序排列,只需遍历该集合,直到找到大于过滤器值的值,然后返回上一个索引。

答案 2 :(得分:0)

以下是使用Linq的方法:

int indexOfMax =
    data.Select((d, i) => new { Data = d, Index = i }) // associate an index with each item
        .Where(item => item.Data.tvd <= maxValue) // filter values greater than maxValue
        .Aggregate( // Compute the max
            new { MaxValue = double.MinValue, Index = -1 },
            (acc, item) => item.Data.tvd <= acc.MaxValue ? acc : new { MaxValue = item.Data.tvd, Index = item.Index },
            acc => acc.Index);

但是在这种情况下,Linq可能不是最佳选择......一个简单的循环会更加清晰。