0

I'm trying to make a random generator that selects a specific number of names from a list and pairs them together.

private void button1_Click(object sender, EventArgs e)
        {
            string[] lines = File.ReadAllLines(@"C:\Users\Brown\source\repos\Generator\bin\names.txt");

            List<string> source = new List<string>();
            int n = int.Parse(textBox1.Text);
            for (int i = 0; i < n; i++)
            {
                source.Add(lines[new Random().Next(lines.Length)]);
            }
            string joinNames = string.Join(" x ", source);

            genResult.Text = joinNames;
        }

I got it to work but when i click the generate button I see duplicates of some names.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179

2 Answers2

1

To select n distinct names instead of the for loop just do this:

Random rnd=new Random();
source=lines.OrderBy(x=>rnd.Next()).Take(n);

Explanation: it will order the line elements in a random order then assigns the first n elements to source

The above solution is not optimal cause it uses the OrderBy method which currently(a Quicksort variant) executes in O(n*log(n)). You can use optimal solution using Fisher-Yates shuffle as introduced in Randomize a List

Mehrdad Dowlatabadi
  • 1,335
  • 2
  • 9
  • 11
  • 1
    Please review proper way of doing it https://stackoverflow.com/questions/273313/randomize-a-listt so you can provide better clones of that in the future (ideally you'd just vote as duplicate instead of suggesting suboptimal approach without corresponding waranings) – Alexei Levenkov Mar 19 '21 at 03:02
1

Rather than loading your data into an array, you should use a collection like a List. Then as you randomly select items from the list, you should remove the record you just selected.

List<String> lines = File.ReadAllLines(@"C:\Users\Brown\source\repos\Generator\bin\names.txt").ToList();
int n = int.Parse(textBox1.Text);
Random rnd = new Random();
List<string> source = new List<string>();
for (int i = 0; i < n; i++)
{
    var tmp = lines[rnd.Next(lines.Count)];
    source.Add(tmp);
    lines.Remove(tmp);
}
string joinNames = string.Join(" x ", source);

genResult.Text = joinNames;
jcwmoore
  • 1,153
  • 8
  • 13