Finding Local Maxima Over a Dynamic Range

前端 未结 6 2122
伪装坚强ぢ
伪装坚强ぢ 2020-12-14 19:17

Working in C#, I need to find all local peaks in a List of doubles and return them as another List doubles. This seems simple enough if I have a set number of values I\'m co

6条回答
  •  忘掉有多难
    2020-12-14 19:28

    Here is my version. It uses a Queue to hold the last windowSize elements, while enumerating the source. Unfortunately I had to use the inefficient ElementAt Linq method to find the tested element in the Queue, because the Queue implementation does not expose its GetElement method (it is internal). For small window sizes this should not be a problem.

    public static IEnumerable<(int, TSource)> LocalMaxima(
        this IEnumerable source, int windowSize)
    {
        var comparer = Comparer.Default;
        var queue = new Queue();
        var testedQueueIndex = (windowSize - 1) / 2;
        var index = testedQueueIndex;
        foreach (var item in source)
        {
            queue.Enqueue(item);
            if (queue.Count >= windowSize)
            {
                var testedItem = queue.ElementAt(testedQueueIndex);
                var queueIndex = 0;
                foreach (var queuedItem in queue)
                {
                    if (queueIndex != testedQueueIndex
                        && comparer.Compare(queuedItem, testedItem) > 0) goto next;
                    queueIndex++;
                }
                yield return (index, testedItem);
            next:
                queue.Dequeue();
                index++;
            }
        }
    }
    

    Usage example:

    var source = "abbacdbbcac".ToCharArray();
    var indexes = Enumerable.Range(0, source.Length);
    var result = source.LocalMaxima(5);
    Console.WriteLine($"Source:  {String.Join(", ", source)}");
    Console.WriteLine($"Indexes: {String.Join("  ", indexes)}");
    Console.WriteLine($"Result:  {String.Join(", ", result)}");
    

    Output:

    Source:  a, b, b, a, c, d, b, b, c, a, c
    Indexes: 0  1  2  3  4  5  6  7  8  9  10
    Result:  (5, d), (8, c)
    

提交回复
热议问题