Yesterday, I asked this question and never really got an answer I was really happy with. I really would like to know how to generate a list of N unique random numbers using a functional language such as Ruby without having to be extremely imperative in style.
Since I didn't see anything I really liked, I've written the solution I was looking for in LINQ:
static void Main(string[] args)
{
var temp = from q in GetRandomNumbers(100).Distinct().Take(5) select q;
}
private static IEnumerable GetRandomNumbers(int max)
{
Random r = new Random();
while (true)
{
yield return r.Next(max);
}
}
Can you translate my LINQ to Ruby? Python? Any other functional programming language?
Note: Please try not to use too many loops and conditionals - otherwise the solution is trivial. Also, I'd rather see a solution where you don't have to generate an array much bigger than N so you can then just remove the duplicates and trim it down to N.
I know I'm being picky, but I'd really like to see some elegant solutions to this problem. Thanks!
Edit:
Why all the downvotes?
Originally my code sample had the Distinct() after the Take() which, as many pointed out, could leave me with an empty list. I've changed the order in which those methods are called to reflect what I meant in the first place.
Apology:
I've been told this post came across as rather snobbish. I wasn't trying to imply that LINQ is better than Ruby/Python; or that my solution is much better than everyone else's. My intent is just to learn how to do this (with certain constraints) in Ruby. I'm sorry if I came across as a jerk.
>>> import random
>>> print random.sample(xrange(100), 5)
[61, 54, 91, 72, 85]
This should yield 5 unique values in the range 0 — 99
. The xrange
object generates values as requested so no memory is used for values that aren't sampled.
In Ruby:
a = (0..100).entries.sort_by {rand}.slice! 0, 5
Update: Here is a slightly different way: a = (0...100).entries.sort_by{rand}[0...5]
EDIT:
and In Ruby 1.9 you can do this:
Array(0..100).sample(5)
Hmm... How about (Python):
s = set()
while len(s) <= N: s.update((random.random(),))
I will forgo the simplest solutions using the 'random' module since I take it that's not really what you are after. Here's what I think you are looking for in Python:
>>> import random
>>>
>>> def getUniqueRandomNumbers(num, highest):
... seen = set()
... while len(seen) < num:
... i = random.randrange(0, highest)
... if i not in seen:
... seen.add(i)
... yield i
...
>>>
To show you how it works:
>>> list(getUniqueRandomNumbers(10, 100))
[81, 57, 98, 47, 93, 31, 29, 24, 97, 10]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With