30

How do I go about picking a random string from my array but not picking the same one twice.

string[] names = { "image1.png", "image2.png", "image3.png", "image4.png", "image5.png" };

Is this possible? I was thinking about using

return strings[random.Next(strings.Length)];

But this has the possibility of returning the same string twice. Or am I wrong about this? Should I be using something else like a List to accomplish this. Any feedback is welcome.

atrljoe
  • 8,031
  • 11
  • 67
  • 110
  • 5
    That sounds like you want to *shuffle* the array, and then just iterate over the array normally. There are lots of shuffling questions on Stack Overflow. – Jon Skeet Jul 14 '11 at 14:53
  • 1
    @Atrljoe - You do understand that returning the same string twice would be a random result right? If you don't want to get the same result twice what you want cannot be described as a random result. – Security Hound Jul 14 '11 at 15:07
  • @Ramhound of course it would be random. It wouldn't be a sequence of *independent* events, but it would still be random. – CodesInChaos Jul 14 '11 at 15:09
  • @ramhound I understand its not completely random, but in this case, if I ask a user to pick a image, and it returns all the same images randomly (very unlikely but theoretically possible) then the user has no choice. I dont need it to be perfect just enough to get me random looking results. – atrljoe Jul 14 '11 at 15:10
  • I have answered this [random item from an array][1] [1]: http://stackoverflow.com/questions/1392819/fastest-way-to-get-a-random-value-from-a-string-array-in-c – mr.memo Jun 05 '14 at 02:35

8 Answers8

41

The simplest way (but slow for large lists) would be to use a resizeable container like List and remove an element after picking it. Like:

var names = new List<string> { "image1.png", "image2.png", "image3.png", "image4.png", "image5.png" };

int index = random.Next(names.Count);
var name = names[index];
names.RemoveAt(index);
return name;

When your list is empty, all values were picked.

A faster way (especially if your list is long) would be to use a shuffling algorithm on your list. You can then pop the values out one at a time. It would be faster because removing from the end of a List is generally much faster than removing from the middle. As for shuffling, you can take a look at this question for more details.

Community
  • 1
  • 1
Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
37

Try this code below

string[] Titles = { "Excellent", "Good", "Super", "REALLY GOOD DOCTOR!", "THANK YOU!", "THE BEST", "EXCELLENT PHYSICIAN", "EXCELLENT DOCTOR" };

comments_title.Value=Titles[new Random().Next(0,Titles.Length) ] ;
Origin
  • 2,009
  • 5
  • 19
  • 19
Bharat Kumar
  • 371
  • 3
  • 2
  • 4
    In the future, try to add a little more description to your posts. Good idea though! :) – davehale23 Dec 10 '12 at 22:47
  • I always thought that all comments were honest and not automated and those that received good reviews were actually good. – Zurechtweiser Dec 23 '14 at 13:27
  • 1
    if it picks max value (Titles.Length) this will cause IndexOutOfRangeException. Otherwise it works well. (Just do Titles.Length - 1) – Gober Aug 27 '15 at 12:47
  • 3
    @Gober The upper limit is exclusive, so that won't be a problem: https://msdn.microsoft.com/en-us/library/2dx6wyd4(v=vs.110).aspx – Ben Visness Nov 11 '15 at 05:22
  • Why I generate that always give me same number? https://dotnetfiddle.net/1C9CcL – Trung Jul 08 '20 at 08:12
  • Do not use `new Random()` inside a for loop, It will give you same number every time as it is called too soon. Declare a Random object outside the loop and use that reference inside the loop. – Vishnu Babu Oct 18 '20 at 04:10
5

You can shuffle the array in a first step, and then simply iterate over the shuffled array.
This has the advantage of being O(n) compared to O(n^2) the RemoveAt based implementations have. Of course this doesn't matter much for short arrays.

Check Jon Skeet's answer to the following question for a good(all orders are equally likely) implementation of shuffe: Is using Random and OrderBy a good shuffle algorithm?

Community
  • 1
  • 1
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
2

The best thing to do is just create a duplicate list, then as you randomly pick out a string, you can remove it from the duplicate list so that you can't pick it twice.

Icemanind
  • 47,519
  • 50
  • 171
  • 296
2

The logic you could use is as follows:

1) Pick a random integer over the range equal to the length of your array. You can do this using the System.Random class.

2) Use the string corresponding to that array index

3) Delete the item with that index from the array (may be easier with a list)

Then you can pick again and the same string won't appear. The array will be one element shorter.

samb8s
  • 427
  • 6
  • 16
1
//SET LOWERLIMIT
cmd = new SqlCommand("select min(sysid) as lowerlimit from users", cs);
int _lowerlimit = (int) cmd.ExecuteScalar();
lowerlimit = _lowerlimit;

//SET UPPERLIMIT
cmd = new SqlCommand("select max(sysid) as upperlimit from users", cs);
int _upperlimit = (int) cmd.ExecuteScalar();
upperlimit = _upperlimit;

//GENERATE RANDOM NUMBER FROM LOWERLIMIT TO UPPERLIMIT
Random rnd = new Random();
int randomNumber = rnd.Next(lowerlimit, upperlimit+1);

//DISPLAY OUTPUT
txt_output.Text += randomNumber;
Vikdor
  • 23,934
  • 10
  • 61
  • 84
devkiat
  • 11
  • 2
1

Use the below utility method

public static class ListExtensions
{
    public static T PickRandom<T>(this List<T> enumerable)
    {
        int index = new Random().Next(0, enumerable.Count());
        return enumerable[index];
    }
}

Then call the below way

string[] fruitsArray = { "apple", "orange"};
string inputString = fruitsArray.ToList().PickRandom();
Siddarth Kanted
  • 5,738
  • 1
  • 29
  • 20
1

You would need to keep track of the ones you have used, preferably in a List if you don't want/can't to modify the original array. Use a while loop to check that it hasn't been used, and then add it to the "used" list.

Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
  • 4
    OK, suppose there are a thousand items in the original list, and 999 items in the "used" list. Your plan is to keep on generating random numbers until you hit the one in a thousand? Your list picking algorithm is going to get slower and slower. This is a poor algorithm for longer lists. – Eric Lippert Jul 14 '11 at 15:06