Взвешенный случайный выбор из массива в рубинах / рельсах - PullRequest
3 голосов
/ 23 марта 2011

У меня есть модель в Rails, из которой я хочу выбрать случайную запись.До сих пор я делал это с помощью именованной области видимости:

named_scope :random,  lambda { { :order=>'RAND()', :limit => 1  } }

Но теперь я добавил в модель целочисленное поле 'weight', представляющее вероятность, с которой следует выбирать каждую строку.

Как мне теперь сделать взвешенный случайный выбор?

Я нашел и опробовал два метода на snippets.dzone.com, которые расширили класс Array и добавили взвешенную случайную функцию, но обане работал или не выбирал случайные предметы для меня.

Я использую REE 1.8.7 и Rails 2.3.

Ответы [ 2 ]

5 голосов
/ 23 марта 2011

Может быть, я понимаю это совершенно неправильно, но не могли бы вы просто использовать столбец «вес» в качестве коэффициента для случайного числа? (В зависимости от Db могут потребоваться некоторые меры предосторожности для предотвращения переполнения продукта.)

named_scope :random,  lambda { { :order=>'RAND()*weight', :limit => 1  } }
0 голосов
/ 27 ноября 2012

В одном запросе вы должны:

  • вычислить общий вес
  • умножить на случайный коэффициент, чтобы получить пороговое значение веса
  • снова сканировать с помощью суммирования таблицыдо достижения порогового значения веса.

В SQL это будет выглядеть так (не пытались по-настоящему)

SELECT SUM(weight) FROM table INTO @totalwt;
@lim := FLOOR(RAND() * @totalwt);
SELECT id, weight, @total := @total + weight AS cumulativeWeight
     FROM table WHERE cumulativeWeight < @lim, (SELECT @total:=0) AS t;

Вдохновлено Оптимальный запрос для извлечениянакопленная сумма в MySQL

...