From: 7stud -- Date: 2007-10-30T09:43:30+09:00 Subject: Re: find the closest items in an array to a given value. > 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 -- Posted via http://www.ruby-forum.com/.