Получить индекс List.Max? - PullRequest
       6

Получить индекс List.Max?

3 голосов
/ 16 апреля 2019

У меня есть список

List<double> nums = new List<double> {0.2, 5.0, 12.0};

, и я пытаюсь найти элемент, для которого element-element^2 является наибольшим.Я могу запустить

nums.Max(num => num - Math.Pow(num, 2))

, чтобы найти максимум, но как мне тогда получить индекс этого элемента, который идентифицирует как выдающее наибольшее значение при оценке num - Math.Pow(num, 2)?IndexOf не будет работать, потому что значение, возвращаемое Max, является не значением фактического элемента, который дает наибольшее значение при применении, а значением всего выражения.

Я смотрел на Получить индекс максимального элемента , но, похоже, он охватывает Max в случае, когда он возвращает фактический элемент и, таким образом, IndexOf работает.Я могу только представить, что существует простой подход к решению моего дела, потому что Max повторяет список в любом случае.

Ответы [ 4 ]

4 голосов
/ 16 апреля 2019

Иногда просто сделать это с помощью старого доброго цикла

double maxValue = Double.MinValue;
int indexOfMax = -1;
for (int i = 0; i < nums.Count; i++) {
    double x = nums[i];
    double y = x - x * x;
    if (y > maxValue) {
        maxValue = y;
        indexOfMax = i;
    }
}
double element = nums[indexOfMax];
3 голосов
/ 16 апреля 2019

В одном запросе Linq (хотя не гарантируется лучшая производительность)

List<double> nums = new List<double> { 0.2, 5.0, 12.0 };
var index = nums.Select((n, i) => new { Result = n - n * n, Index = i })
                .Aggregate(new { Result = Double.MinValue, Index = -1 }, (a, b) => (a.Result > b.Result) ? a : b)
                .Index;

Более эффективный подход, делающий это только одним анализом списка, состоит в том, чтобы создать собственное расширение .Max() и затем вызвать его в списке.

public static int MaxIndexByCustomRule(this IEnumerable<double> sequence)
    {
        int index = 0;
        int maxIndex = -1;
        double maxResult = double.MinValue;
        foreach (var value in sequence)
        {
            var tempResult = value - value * value;

            if (tempResult > maxResult)
            {
                maxResult = tempResult;
                maxIndex = index;
            }

            index++;
        }
        return maxIndex;
    }

Звоните:

List<double> nums = new List<double> { 0.2, 5.0, 12.0 };
nums.MaxIndexByCustomRule();
1 голос
/ 16 апреля 2019

Вы можете использовать Linq.Выберите элемент и его индекс и рассчитайте значение для каждого элемента.Затем сортируйте (по убыванию, в вашем случае) и берите верхний элемент.Тот же текст, что и код:

List<double> nums = new List<double> { 0.2, 5.0, 12.0 };

var index = nums.Select((d, i) => new {index = i, value = d - d * d})
    .OrderByDescending(x => x.value)
    .Take(1)
    .Select(x => (int?) x.index)
    .FirstOrDefault();

if (index == null)
    Console.WriteLine("nums is empty");
else
    Console.WriteLine($"index is {index}");
0 голосов
/ 17 апреля 2019
    private static int index = -1;
    private static double value = Double.MinValue;
    [TestMethod]
    public void MaxTest()
    {

        List<double> nums = new List<double> { 0.2, 5.0, 12.0 };
        var x = nums.Max(num => Transform(num));
    }


    public double Transform(double n)
    {
        var r = n - Math.Pow(n, 2);
        if (r > value)
        {
            value = r;
            index++;
        }

        return r;
    }

Если вы намереваетесь захватить индекс элемента max, я бы порекомендовал использовать первое решение в этом посте, используя традиционный цикл. Вот что вы можете сделать, если вы все еще хотите использовать функцию max с использованием делегата.

...