[英]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
对于全部i
, 0 <= 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.