Я хотел бы создать эту функцию, которая выбирает случайный элемент из Set:
randElem :: (RandomGen g) => Set a -> g -> (a, g)
Простые списки реализаций могут быть записаны. Например (обновленный код, проверенный рабочий):
import Data.Set as Set
import System.Random (getStdGen, randomR, RandomGen)
randElem :: (RandomGen g) => Set a -> g -> (a, g)
randElem s g = (Set.toList s !! n, g')
where (n, g') = randomR (0, Set.size s - 1) g
-- simple test drive
main = do g <- getStdGen
print . fst $ randElem s g
where s = Set.fromList [1,3,5,7,9]
Но использование !!
приводит к линейной стоимости поиска для больших (случайно выбранных) n
. Есть ли более быстрый способ выбора случайного элемента в наборе? В идеальном случае повторные случайные выборки должны обеспечивать равномерное распределение по всем параметрам, то есть не предпочитают некоторые элементы над другими.
Изменить: в ответах появляются замечательные идеи, поэтому я просто хотел рассказать еще несколько разъяснений о том, что именно я ищу. Я задал этот вопрос с помощью Sets в качестве решения этой ситуации. Я предпочел бы ответы, что
- избегайте использования любой внешней бухгалтерской книги вне встроенных внутренних элементов и
- поддерживать хорошую производительность (лучше, чем O (n) в среднем), хотя функция используется только один раз для уникального набора.
У меня также есть такая любовь к рабочему коду, поэтому ожидайте (как минимум) +1 от меня, если ваш ответ включает рабочее решение.