如何识别浮点数组中的波峰和波谷?

时间:2019-03-06 03:07:45

标签: arrays ruby

我有一个数组,

array = [
  0.43, 
  0.64, # => peak
  0.2, 
 -0.05, 
 -0.15, # => trough
  0.2, # => peak
 -0.1, 
 -0.5, # => trough
 -0.3
]

,在数据中有两个峰和两个谷。这些峰和谷不一定是数组的 min max 。如何通过程序识别那些人?

理想的输出为:

peak_indexes = [1, 5]
trough_indexes = [4, 7]

3 个答案:

答案 0 :(得分:2)

{each_cons(3)提取检查中间项所需的相邻三个项,同时排除在中间有array的第一个或最后一个元素的三元组。

with_index(1)考虑到以下事实:中间array第一个元素的三元组被跳过,因此从1开始对索引编号。

您尚未定义高峰和低谷的含义。如果您打算采用本地的最大值和最小值,那么以下方法将起作用。

array.each_cons(3).with_index(1).select{|a, i| a.max == a[1]}.map(&:last)
# => [1, 5]

array.each_cons(3).with_index(1).select{|a, i| a.min == a[1]}.map(&:last)
# => [4, 7]

或者,如果您的意思是Stefan在我的回答的注释中解释的内容,那么以下内容将起作用:

array
.each_cons(3)
.with_index(1)
.select{|(a1, a2, a3), i| a1 < a2 && a2 > a3}
.map(&:last)
# => [1, 5]

array
.each_cons(3)
.with_index(1)
.select{|(a1, a2, a3), i| a1 > a2 && a2 < a3}
.map(&:last)
# => [4, 7]

答案 1 :(得分:1)

首先,让我们定义峰或谷的含义。

  • 峰值是一个大于其左侧和右侧值的值。
  • 槽的值比左右的值小。

这将使我们能够定义两个有用的功能:

def is_peak?(left_value, value, right_value)
  return value > left_value && value > right_value
end

def is_trough?(left_value, value, right_value)
  return value < left_value && value < right_value
end

现在我们可以遍历数组中的每个元素,并使用这些函数询问该元素是峰还是谷。

array = [0.43, 0.64, 0.2, -0.05, -0.15, 0.2, -0.1, -0.5]
positive_peak_indexes = []
negative_peak_indexes = []
# Loop through the array
array.each_with_index do |elem, i|
  # Make sure we don't get an out of bounds exception
  next if (i-1 < 0) || (i + 1 >= array.length)

  # Now we add to our appropriate arrays if it's a peak/trough
  positive_peak_indexes << i if is_peak?(array[i-1], elem, array[i+1])
  negative_peak_indexes << i if is_trough?(array[i-1], elem, array[i+1])
end
puts "positive_peak_indexes = #{positive_peak_indexes.to_s}"
puts "negative_peak_indexes = #{negative_peak_indexes.to_s}"

答案 2 :(得分:0)

我没有时间测试更多案例,所以也许有一些错误。

无论如何,基本思想是使用索引(Enumerable#each_with_index)压缩每个元素,然后在发生变化时使用方法Enumerable#chunk_while对数组进行切片。最后从大块中提取极端。

最好用一段代码,ary是数据数组。

首先是大块:

chunks = ary.map.with_index{ |x, i| [x,i] }.chunk_while { |x,y| y.first < x.first }

然后收集极端信息:

peaks = chunks.collect { |e| e.first if e.size > 1 }.compact #=> [[0.64, 1], [0.2, 5]]
trough = chunks.collect { |e| e.last if e.size > 1 }.compact #=> [[-0.15, 4], [-0.5, 7]]