我有一个数组,
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]
答案 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]]