It’s crucial to know whether your sequence of values is
always sorted.
arr = […]
sorted_arr = arr.sort
PS: A nice task for #inject.
Unfortunately, from tests I have done in other threads, it appears that
inject is not very efficient, i.e. it’s slow.
Flávio Lisbôa wrote:
def array_between(a=[], v=0.0)
return [] if a.empty?
return [v, a.min] if v < a.min
return [a.max, v] if v > a.max
ret = []
ret.push a.find {|num| num < v}
ret.push a.find {|num| num > v}
ret.push v if ret.size < 2
return ret.sort
end
Just a quick 10-second sketch… Maybe you should have tried this too.
And i know you from other forums too! Nice to see you here trebor!!
That doesn’t work:
a = [1.1, 1.3, 1.4, 2, 2.2, 3]
target = 1.85
p array_between(a, target)
–output:–
[1.1, 2]
detect returns the first value for which block isn’t false, which will
be the first value in the array that is less than the given number. The
op wants the biggest number in that array that is less than the given
number, which could be the last number in the array.
[1,2,3,4,5,6].min { |a,b| (a-value).abs <=> (b-value).abs }
That doesn’t work. It returns only the closest single value.
ary.sort_by { |item| (value-item).abs }.first(n)
That doesn’t work either. It returns the two closes values, which means
that both returned values could be less than or greater than the given
number. The op wants the two closest number that is lower than the
given number and the closest number that is higher than the given
number.
The following are two solutions that appear to do what the op wants.
The first one stores the closest lower value and the closest higher
value in two variables as it steps through the array:
a = [ 1.25, 1, 3, 1.9, 1.95, 2.1, 2.2, 1.5]
target = 1.85
closest_lower = nil
closest_higher = nil
a.each do |elmt|
if elmt < target
if !closest_lower or elmt > closest_lower
closest_lower = elmt
end
elsif elmt > target
if !closest_higher or elmt < closest_higher
closest_higher = elmt
end
else #if elmt == target
#do something
end
end
Surprisingly, this is slightly faster–even for very large arrays:
target = 1.85
less_than = []
greater_than = []
a.each do |elmt|
if elmt < target
less_than << elmt
elsif elmt > target
greater_than << elmt
end
end
puts less_than.max
puts greater_than.min