我有一个阵列,
array = [ 0.43, 0.64,#=>峰 0.2, -0.05, -0.15,#=>槽 0.2,#=>峰 -0.1, -0.5,#=>槽 -0.3]在…中有两个峰和两个低谷
首先让我们来定义什么是高峰或低谷的意义。
这将允许我们定义两个有用的功能:
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}"
each_cons(3) 提取检查中期所需的相邻三个术语,同时排除具有第一个或最后一个元素的三元组 array 在中间。
each_cons(3)
array
with_index(1) 考虑到三元组与第一元素的关系 array 中间被跳过,因此编号从1开始的索引。
with_index(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]
我没有时间测试更多的案例,所以也许有一些bug。
无论如何,基本的想法是用它的索引压缩每个元素( 枚举#each_with_index ),然后使用该方法 枚举#chunk_while 在有变化时切片数组。最后从大块中提取极端。
更好的一段代码, ary 是数据数组。
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]]