在数组中找到最接近的数字给定值

时间:2014-11-12 23:19:21

标签: ruby algorithm ruby-on-rails-4

我正在寻找一种方法,它会将数组中最接近的5个数字返回给我。这是我要让我开始的。我想比较差异,但我觉得必须有一个更简单的方法。

def get_suggested_items
    @suggested_items = []
    new_price = self.price
    products = Product.all
    products.each do |product, difference|
        price = product.price
        old_difference = new_price - product.price
        difference = (new_price - product.price).abs
        while difference < old_difference 
            @suggested_items << product
        end

end

我希望以最优惠的价格将@suggested_items阵列退回

2 个答案:

答案 0 :(得分:4)

SQL就是为这类东西而设计的。将以下类方法添加到Product模型中:

class Product < ActiveRecord::Base

  def self.with_price_nearest_to(price)
    order("abs(products.price - #{price})")
  end
end

然后你可以写:

Product.with_price_nearest_to(3.99).limit(5)

与您在问题中概述的内容相比,此方法具有明显的性能优势。在这种情况下,数据库会为您进行计算和排序,并仅返回ActiveRecord所需的5个产品。当您执行Product.all甚至Product.each时,您强制ActiveRecord为表中的每一行实例化一个模型,随着表变大,这会变得很昂贵。

请注意,此方法仍需要全表扫描;如果您想进一步提高性能,可以在price表上的products列添加索引。

答案 1 :(得分:1)

假设arr是整数的排序数组。 (如果它没有排序,那么排序为第一步。)  我假设你想从数组a = arr[i,5]中找到五个元素的序列,这样a.last-a.first对于所有i0 <= i <= arr.size-4来说都是最小的。如果这是正确的,那么它只是:

start_index = (arr.size-4).times.min_by { |i| arr[i+4]-arr[i] }

假设

arr = [1, 2, 4, 5, 8, 9, 11, 12, 13, 15, 17, 19, 23, 24, 24, 25, 30]
start_index = (arr.size-4).times.min_by { |i| arr[i+4]-arr[i] }
  #=> 4

所以&#34;最接近&#34;五个数字将是:

arr[4,5]
  #=> [8, 9, 11, 12, 13]