在C#中工作,我需要在双精度列表中找到所有本地峰值,并将它们作为另一个列表双精度返回.这看起来很简单,如果我在任何给定的"窗口"值中有一组我正在比较的值,但我需要能够将这个窗口大小实际传递给函数本身.这可能令人困惑,但基本上我需要这样的东西:
public List<double> FindPeaks(List<double> values, double rangeOfPeaks)
Run Code Online (Sandbox Code Playgroud)
如果'rangeOfPeaks'为5,则将'current'值与其每一侧的2个值进行比较,以确定它是否为峰值.如果'rangeOfPeaks'为11,则将当前值与每侧的5个值进行比较.我认为这是一个非常基本的算法,但是,我找不到像这样检测峰值的任何好方法都没有成功.有没有人曾经这样做过?任何帮助都将不胜感激.提前致谢!
小智 8
我建议对Levy的帖子进行一些修改......
1)当指定值IList几乎是直线时,Levy的代码抛出异常.
2)我认为数组中峰的索引是期望的结果.例如,考虑如果我们有两个具有相同双精度的峰值会发生什么?行动.更改为返回指定IList中峰值的索引.
public static IList<int> FindPeaks(IList<double> values, int rangeOfPeaks)
{
List<int> peaks = new List<int>();
double current;
IEnumerable<double> range;
int checksOnEachSide = rangeOfPeaks / 2;
for (int i = 0; i < values.Count; i++)
{
current = values[i];
range = values;
if (i > checksOnEachSide)
{
range = range.Skip(i - checksOnEachSide);
}
range = range.Take(rangeOfPeaks);
if ((range.Count() > 0) && (current == range.Max()))
{
peaks.Add(i);
}
}
return peaks;
}
Run Code Online (Sandbox Code Playgroud)
可能有更有效的方法,但LINQ使这非常简单
static IList<double> FindPeaks(IList<double> values, int rangeOfPeaks)
{
List<double> peaks = new List<double>();
int checksOnEachSide = rangeOfPeaks / 2;
for (int i = 0; i < values.Count; i++)
{
double current = values[i];
IEnumerable<double> range = values;
if( i > checksOnEachSide )
range = range.Skip(i - checksOnEachSide);
range = range.Take(rangeOfPeaks);
if (current == range.Max())
peaks.Add(current);
}
return peaks;
}
Run Code Online (Sandbox Code Playgroud)