简体   繁体   English

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

[英]Find closest numbers in array to given value

I'm looking to create a method that will return to me the 5 closest numbers in an array. 我正在寻找一种方法,该方法将向我返回数组中5个最接近的数字。 Here is what I have to get me started. 这是我必须开始的工作。 I'm looking to compare differences but I feel there has to be a simpler way . 我想比较差异,但是我觉得必须有一种更简单的方法。

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

I'm looking to have returned the array @suggested_items with the 5 closest products by the price 我希望以价格返回最接近的5个产品的数组@suggested_items

SQL was designed for this sort of thing. SQL是为这种事情而设计的。 Add the following class method to your Product model: 将以下类方法添加到您的Product模型中:

class Product < ActiveRecord::Base

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

Then you can write: 然后您可以编写:

Product.with_price_nearest_to(3.99).limit(5)

There is a distinct performance advantage to this approach over what you outlined in your question. 与您在问题中概述的方法相比,此方法具有明显的性能优势。 In this case, the database does the calculation and sorting for you and returns to ActiveRecord only the 5 products that you need. 在这种情况下,数据库将为您进行计算和排序,并仅将您需要的5种产品返回给ActiveRecord。 When you do Product.all or even Product.each you're forcing ActiveRecord to instantiate a model for every row in your table, which gets expensive as the table gets larger. 当您执行Product.all甚至是Product.each您都在迫使ActiveRecord为表中的每一行实例化一个模型,随着表的增大,该模型会变得很昂贵。

Note that this approach still requires a full table scan; 注意,这种方法仍然需要全表扫描。 if you want to improve the performance further, you can add an index to price column on the products table. 如果要进一步改善性能,可以在products表的price列中添加索引。

Suppose arr is a sorted array of integers. 假设arr是一个有序的整数数组。 (If it's not sorted, then sort as the first step.) I assume you want to find a sequence of five elements from the array, a = arr[i,5] , such that a.last-a.first is minimum for all i , 0 <= i <= arr.size-4 . (如果未排序,则作为第一步进行排序。)我假设您想从数组a = arr[i,5]找到五个元素的序列,这样a.last-a.first对于全部i0 <= i <= arr.size-4 If that's correct, then it's simply: 如果是正确的话,那就很简单:

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

Suppose 假设

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

So the "closest" five numbers would be: 因此,“最接近的”五个数字将是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM