user230982
user230982

Reputation: 31

Select distinct and random numbers from list

I have list of 70 question numbers out of which I want to select 50 random and unique questions. How can I do this?

Here is what I have so far:

static Random random = new Random();

static void Main(string[] args)
{
    List<int> questionNumbers = new List<int>();
    for (int i = 0; i < 70; i++)
    {
        questionNumbers.Add(i);
    }

    List<int> randomAndUniqueNumbers = GenerateRandom(50);
}

public static List<int> GenerateRandom(int count)
{
    // ????
}

Upvotes: 3

Views: 733

Answers (7)

Enigmativity
Enigmativity

Reputation: 117175

Try this:

List<int> randomAndUniqueNumbers =
    Enumerable
        .Range(0, 70)
        .OrderBy(x => random.Next())
        .Take(50)
        .ToList();

Upvotes: 1

Clay Ver Valen
Clay Ver Valen

Reputation: 1073

Without getting into theory, DO NOT do any of the earlier answers. You should be implementing a Fisher-Yates Shuffle and then take the first 50 elements of the shuffled list.

To save you some time I've put an implementation below. The Shuffle function is generic so if later you decide to actually shuffle questions (e.g. a List<Question> instead of numbers it will still work for you:

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

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = Enumerable.Range(1, 70).ToList();
        Shuffle(numbers);
        foreach (int number in numbers.Take(50))
        {
            Console.WriteLine(number);
        }
        Console.ReadLine();
    }

    static void Shuffle<T>(IList<T> items)
    {
        Random rand = new Random();
        for (int i = items.Count - 1; i > 0 ; i--)
        {
            int j = rand.Next(i + 1); // Returns a non-negative random integer that is less than the specified maximum - MSDN

            T temp = items[i];
            items[i] = items[j];
            items[j] = temp;
        }
    }
}

Upvotes: -1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186833

Well, just remove the taken question (or its index) from the list:

static Random random = new Random();

private static IEnumerable<int> GenerateRandom(int takeCount, int questionCount) {
  List<int> numbers = Enumerable
    .Range(0, questionCount)
    .ToList();

  for (int i = 0; i < takeCount; ++i) {
    int index = random.Next(numbers.Count);

    yield return numbers[index];

    numbers.RemoveAt(index);
  }
}

static void Main(string[] args) {
   List<int> randomAndUniqueNumbers = GenerateRandom(50, 70).ToList();
}

Upvotes: 0

Lei Yang
Lei Yang

Reputation: 4355

    static Random random = new Random();
    static List<int> questionNumbers = new List<int>();

    static void Main(string[] args)
    {
        for (int i = 0; i < 70; i++)
        {
            questionNumbers.Add(i);
        }

        List<int> randomAndUniqueNumbers = GenerateRandom(50);
    }

    //This function doesn't require index in questionNumbers
    //to be from 0 and continuous
    public static List<int> GenerateRandom(int count)
    {
        List<int> lst = new List<int>();
        List<int> q = questionNumbers.ToList();
        for (int i = 0; i < count; i++)
        {
            int index = random.Next(0, q.Count);
            lst.Add(q[index]);
            q.RemoveAt(index);
        }
        return lst.OrderBy(x => x).ToList();
    }

Upvotes: 0

jdweng
jdweng

Reputation: 34433

Try this

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

namespace ConsoleApplication61
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    public class Question
    {
        private static Random rand = new Random();
        public static List<Question> questions { get; set; }
        public string question { get; set; }
        public int randomNumber { get; set; }

        public void Shuffle()
        {
            foreach(Question question in questions)
            {
                question.randomNumber = rand.Next();
            }
            questions = questions.OrderBy(x => x.randomNumber);
        }

    }
}

Upvotes: -1

Jenish Rabadiya
Jenish Rabadiya

Reputation: 6766

Try using extension methods of Linq.

class Program
{
    static void Main(string[] args)
    {
        List<int> questionNumbers = new List<int>();
        for (int i = 0; i < 70; i++)
        {
            questionNumbers.Add(i);
        }

        List<int> randomAndUniqueNumbers = questionNumbers.GenerateRandom(50);
    }


}

public static class Extensions
{
    static Random random = new Random();
    public static List<T> GenerateRandom<T>(this List<T> collection, int count)
    {
        return collection.OrderBy(d => random.Next()).Take(count).ToList();
    }
}

Dot net fiddle is here

Upvotes: 4

sQuir3l
sQuir3l

Reputation: 1383

This should do it. You might want to bound the random number by putting in a min and max into random.Next(min, max)

public static List<int> GenerateRandom(int count)
{
    var result = new HashSet<int>();
    while (result.Count < 50)
    {
        result.Add(random.Next());
    }

    return result.ToList();
}

Upvotes: -3

Related Questions