Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use Linq to generate unique random number

Tags:

linq

here is my Linq code to generate a list of random numbers which contains 10 numbers ranging from 0 to 20

Random rand = new Random();
var randomSeq = Enumerable.Repeat(0, 10).Select(i => rand.Next(0,20));

Result:

6

19

18

7

18

12

12

9

2

18

as you can see i have three 18s and two 12s..

I have tried to use Distinct() function, but it will not fill up the list (e.g only fill up 8 out of 10 numbers) Question: How can I generate unique number (i.e non repeatable numbers ) Many thanks

like image 429
Kiddo Avatar asked Dec 03 '22 12:12

Kiddo


2 Answers

You want to generate a random permutation of the numbers 0 to 19 and pick 10 of these numbers. The standard algorithm for generating a random permutation is Fisher-Yates shuffle. After generating a random permutation you can just pick the first 10 numbers.

It is not to hard to come up with an ad-hoc algorithm like repeatedly choosing a new number if a collision occured but they usually fail to have good statistical properties, have nondeterministic runtime or don't even guarantee termination in the worst case.

Note that this solution is no good choice if the numbers are of different order. Generating a permuation of the numbers below a million only to pick ten is not the smartest thing one can do.

UPDATE

I just realized that you can just stop the algorithm after generating the first ten elements of the permutation - there is no need to build the whole permutation.

like image 200
Daniel Brückner Avatar answered Dec 28 '22 23:12

Daniel Brückner


In functional programming it is usual to create infinite sequences. It might sound a little bizarre at first but it can be very usefull at some situations. Supose you have an extention as such:

public static class EnumerableExtentions
{
    public static IEnumerable<T> Infinite<T>(Func<int, T> generator)
    {
        int count = 0;
        checked {
            while (true)
                yield return generator(count++);
        }
    }
}

I can use it to create infinite sequences like:

var oddNumbers = EnumerableExtentions.Infinite(n => 2*n + 1)

That is an infinite sequence of all odd numbers. I could take only the first 10, for example:

oddNumbers.Take(10);

would yield:

1 3 5 7 9 11 13 15 17 19

Because of the defered execution, we don´t get a StackOverflowException (you gotta be carefull though).

The same principle can be used to create an infinite random sequence, distinct it and then taking the first 10:

var r = new Random();
var randomNumbers = EnumerableExtentions
                    .Infinite(i=> r.Next (0, 20))
                    .Distinct()
                    .Take(10);

If you need, you can make an OrderBy(s=>s) at the end.

like image 40
Fabio Marreco Avatar answered Dec 29 '22 00:12

Fabio Marreco