2014-11-12 3 views
0

Я ищу, чтобы создать метод, который вернет мне 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 массива с 5 ближайшими продуктами по цене

+1

Что ваш входной выборки и ожидаемые результаты? –

+0

Эй, я хочу вернуть массив @sposed_items с 5 ближайшими продуктами по цене –

+0

Да, мы знаем эту часть. Мы не знаем, как выглядят ваши данные, поэтому дайте минимальный пример того, что будет в вашей базе данных, и какие значения будут выбраны. Не ожидайте, что мы представим такую ​​вещь, потому что вы никогда не знаете, что вы вернете взамен. –

ответ

3

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.

+0

Это имеет большой смысл! Спасибо, что это сработало как шарм! –

1

Предположим, arr - это отсортированный массив целых чисел. (Если он не отсортирован, то сортируйте как первый шаг.) Я предполагаю, что вы хотите найти последовательность из пяти элементов из массива, a = arr[i,5], так что a.last-a.first минимально для всех i, 0 <= 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 

Так что «ближайшие» пять чисел будет:

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