How to use Linq to generate a unique random number

here is my Linq code to create a list of random numbers that 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 18 s and 12 s.

I tried to use the Distinct () function, but it will not fill out the list (for example, just fill in 8 out of 10 numbers) Question: How can I generate a unique number (i.e. non repeatable numbers) Thank you very much

+3
source share
10 answers

Can you do something like this?

Random rand = new Random();
var randomSeq = Enumerable.Range(0, 20).OrderBy(i => rand.Next(0,20)).Take(10);
-4
source

0 19 10 . Fisher-Yates shuffle. 10 .

ad-hoc, , , , .

, , . - , .

UPDATE

, - .

+8

. , . , :

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

, :

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

. 10, :

oddNumbers.Take(10);

:

1 3 5 7 9 11 13 15 17 19

- StackOverflowException ( , ).

, , 10:

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

, OrderBy (s = > s) .

+5

LINQ exchange, LINQ , , .

( ):

LINQ OrderBy

// create and populate the original list with 20 elements
   List<int> MyList = new List<int>(20);
   for (int i = 0; i < 20; i++)
   MyList.Add(i);
// use System.GUID to generate a new GUID for each item in the list
   List<int> RandomList = MyList.OrderBy(x => System.Guid.NewGuid()).ToList();

LINQ OrderBy GUID.

10 , .

, System.Guid.NewGuid() , Shuffle Fisher-Yates, .

+3

:

Enumerable.Range(0, 20)
          .OrderBy(x => Guid.NewGuid().GetHashCode())
          .Distinct()
          .Take(10)
          .ToArray();
+2

. ( ) .

static class Excensions
{
    public static T PopAt<T>(this List<T> list, int index)
    {
        T ret = list[index];
        list.RemoveAt(index);
        return ret;
    }
}

class Program
{
    static void Main()
    {
        Random rng = new Random();
        int length = 10; //sequence length
        int limit = 20; //maximum value
        var avail = Enumerable.Range(0, limit).ToList();
        var seq = from i in Enumerable.Range(0, length)
                  select avail.PopAt(rng.Next(avail.Count));
    }
}
+1

:

    static IEnumerable<int> RandomNumbersBetween(int min, int max) 
    {
        int availableNumbers = (max - min) + 1 ;
        int yieldedNumbers = 0;

        Random rand = new Random();
        Dictionary<int, object> used = new Dictionary<int, object>();

        while (true)
        {
            int n = rand.Next(min, max+1); //Random.Next max value is exclusive, so add one
            if (!used.ContainsKey(n))
            {
                yield return n;
                used.Add(n, null);

                if (++yieldedNumbers == availableNumbers)
                    yield break;
            }
        }
    }

IEnumerable, LINQ IEnumerable:

RandomNumbersBetween(0, 20).Take(10)

, , :

RandomNumbersBetween(1, 1000).Where(i => i%2 == 1).Take(100)

Et cetera.

Edit:

, , min max.

, , , 10 0 20 0 1000.

(max - min).

+1
source

save the generated result in an array, so at any time when you create a new number check, if it was generated earlier, if so, generate another, otherwise take a number and save it in the array

0
source

Using the RepeatUntil user extension and using closures:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    public static class CoolExtensions
    {
        public static IEnumerable<TResult> RepeatUntil<TResult>( TResult element, Func<bool> condition )
        {
            while (!condition())
                yield return element;
        }
    }

    class Program
    {
        static void Main( string[] args )
        {
            Random rand = new Random();
            HashSet<int> numbers = new HashSet<int>();

            var randomSeq = CoolExtensions.RepeatUntil( 0, () => numbers.Count >= 10).Select( i => rand.Next( 0, 20 ) ).Select( x => numbers.Add(x));

            // just used to evaluate the sequence
            randomSeq.ToList();

            foreach (int number in numbers)
                Console.WriteLine( number );

            Console.ReadLine();
        }
    }
}
0
source

Why not order randomly? like this

var rnd = new Random();
var randomSeq = Enumerable.Range(1,20).OrderBy(r => rnd.NextDouble()).Take(10).ToList();
0
source

Source: https://habr.com/ru/post/1754764/


All Articles