1

I know how to randomly fill an array with integers.

But say I have Apple, Banana and Orange.
I want to fill an array with these 3 fruits in a random order.
How would I do this? Should I use Fisher-Yates Shuffle for this?

My array has to be written like this:

string[] basket = new string[20];
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • Loop over the size of the array and select a random string to insert in each loop iteration? – David Apr 24 '17 at 15:30
  • If you don't care about dups just loop and randomly select one. If you do there are many previous questions about shuffling – Gilad Green Apr 24 '17 at 15:31
  • I think OP does care about duplicates because he mentioned Fisher-Yates shuffle, which gets a permutation of a set by shuffling the set. – Blake Thingstad Apr 24 '17 at 15:35
  • Does the result have to be truly random? You could have a `List` of all possible results, and with some simple LINQ you could `OrderBy(x => Guid.NewGuid())`, then `Take(3).ToArray()` – maccettura Apr 24 '17 at 15:38
  • can the source be a list? –  Apr 24 '17 at 15:38
  • 1
    I feel like even if we said, "Yes, use Fisher-Yates shuffle to do this" then you would still be stuck as your problem appears to be "How do I randomly select a string? `Random.Next` deals with numbers, not strings" -- I mean to say that if this is your question then be explicit and don't confuse yourself with an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). @BlakeThingstad then why is his array size 20? "Use Fisher-Yates shuffle for every 3 entries, then start over and continue doing that until the array is filled" I guess would make sense. – Quantic Apr 24 '17 at 15:40
  • It has to be an array, duplicates dosn't matter. Filling 20 spots with 3 fruits is bound to be duplicates I think. –  Apr 24 '17 at 15:41
  • @Quantic - Yes, I can handle the Random.Next, but what should I use for strings? –  Apr 24 '17 at 15:43
  • @Quantic you could still use the Fisher-Yates shuffle because it iterates over the collection and uses the current index and a random index to swap items. But no point in going into that further because OP clearly doesn't need the Fisher-Yates shuffle. I was actually furiously working on a couple extension methods for swapping and shuffling a generic IEnumerable, but found out this wouldn't fit with OP's requirements anyways. – Blake Thingstad Apr 24 '17 at 15:55

4 Answers4

0

Create an IEnumerable in the desired size and then for each item select a random index from your strings array

var desiredArrayLength = 20; // Should be const or from config

var strings = new[] { "Apple", "Banana", "Orange" };
Random random = new Random();

var basket = Enumerable.Range(1, desiredArrayLength)
                       .Select(i => strings[random.Next(strings.Length)]).ToArray();

Make sure that no matter how you decide to initialize basket do not do something like new string[20] - use a const/config value so it won't be a magic number

More about magic numbers: What is a magic number, and why is it bad?

Community
  • 1
  • 1
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • Why should't I use what you call a magic number? This is the way they are teaching us at school. The examples for this assignment does just that, new string[20] :( –  Apr 24 '17 at 15:54
  • 1
    @Tenakey - see link added to answer :) If they want you to have it with the magic number then you can do it for the assignment - but do know what are the good patterns to do :) – Gilad Green Apr 24 '17 at 15:55
0

If you add all your string in a list you can then loop and select randomly one value and add it to your array

List<string> list = new List<string>();

list.Add("Apple");
list.Add("Banana");
list.Add("Orange");

string[] basket = new string[20];

Random rd = new Random();

for(int i = 0; i < basket.Length; i++)
{
    int randomValue = rd.Next(list.Count);

    basket[i] = list[randomValue];
}
I.B
  • 2,925
  • 1
  • 9
  • 22
  • All answers are probably good on this topoc, but I feel in this one I can actually understand whats going on at this point of my education. Therfore I mark this as accepted. Thanks! –  Apr 24 '17 at 16:34
0

Build an extension to repeat and shuffle any collection (this one uses Fisher-Yates)

public static class EnumerableExtensions
{
    private static readonly Random _rng = new Random();

    public static IEnumerable<T> Shuffle<T>( this IEnumerable<T> collection, Random rng = null )
    {
        rng = rng ?? _rng;

        var list = collection.ToList();
        for (int i = 0; i < list.Count; i++)
        {
            var j = i + rng.Next( list.Count - i );
            yield return list[j];
            if (i != j)
            {
                list[j] = list[i];
            }
        }
    }

    public static IEnumerable<T> Repeat<T>(this IEnumerable<T> collection, int count)
    {
        for ( int i = 0; i < count; i++ )
        {
            foreach ( var item in collection )
            {
                yield return item;
            }
        }
    }

}

and use it like

string[] fruits = new string[] { "Apple", "Banana", "Orange" };
string[] basket = fruits
    .Repeat( ( 20 + fruits.Length - 1 ) / fruits.Length )
    .Shuffle()
    .Take( 20 )
    .ToArray();

More random can be achieved by

public static class EnumerableExtensions
{
    ...

    public static IEnumerable<T> RandomRepeat<T>(this IEnumerable<T> collection, int count, Random rng = null)
    {
        rng = rng ?? _rng;
        var list = collection.ToList();
        for ( int i = 0; i < count; i++ )
        {
            var j = rng.Next( list.Count );
            yield return list[j];
        }
    }
}

and

string[] fruits = new string[] { "Apple", "Banana", "Orange" };
string[] basket = fruits.RandomRepeat( 20 ).ToArray();
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • The shuffling is fine but how will he randomly populate the array to start with (which is the question) :) – Gilad Green Apr 24 '17 at 15:56
  • @GiladGreen What is the difference of filling ordered, shuffle and return that, or filling randomly? Both have a random order – Sir Rufo Apr 24 '17 at 15:59
  • Filling randomly is different than filling and then ordering randomly. If filling a size 20 array with 3 different values then how many do you want to have from each value? If you do not fill it randomly then you actually already decide how many you will have from each item – Gilad Green Apr 24 '17 at 16:00
0

So, I am at school right now, so I can't test the code myself but if I'm right the code could go something like this.

int Strings = 3;
string[] a1 = new[] {
  "Apple",
  "Banana",
  "Orange",
}

Random r1 = new Random();

string b1 = a1[r1.Next(0, a1.Length)];
listBox1.Items.Add(b1);

string b2 = a1[r1.Next(0, a1.Length)];
if (listBox1.Items.Contains(b2))
{
  b2 = a1[r1.Next(0, a1.Length)];
  listBox1.Items.Add(b2);
}
else
{
  listBox1.Items.Add(b2);
}
string b3 = a1[r1.Next(0, a1.Length)];
if (listBox1.Items.Contains(b3))
{
  b3 = a1[r1.Next(0, a1.Length)];
  listBox1.Items.Add(b3);
}
else
{
  listBox1.Items.Add(b3);
}

Here's also a C# class that can help you. https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx

It also checks whether the string is in the listbox and reroutes it, so it gets a different one your gonna want to make a check that continues it when it happens to be the same string.

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
0x59
  • 99
  • 1
  • 10