Random getting value from a range or a specific value

84 Views Asked by At

I have a list of classes/objects and I need to get a random item from the list. In a particular case, I need to take a random item from a specific range OR a specific index. Meaning it's not just a

Item item = List[Random.Next(2,10)]; //take one random item between index 2 and index 9

(to make an example) but I'd need something like "the random value must be between 2 and 9 (like in the example) OR be 15". I just need to add also the index 15 to the random range. So, is there a simple way to choose different ranges instead of only one range without creating a new List with the items I need? Always for that matter, is there a way to exclude some values from the base range (2,9)?

3

There are 3 best solutions below

5
Svyatoslav Danyliv On

I would increase range and use additional value as exception:

var index = Random.Next(2, 11);
if (index == 10)
    index = 15;
3
Alander On

You can create a RandomRange class, you can create as many as you want and put into a list

public class RandomRange
{
    public int Start { get; set; }
    public int End { get; set; }

    public int Exception { get; set; }

    public RandomRange(int start, int end, int exception)
    {
        Start = start;
        End = end;
        Exception = exception;
    }

    public int getRandomIndex()
    {
        Random random = new Random();

        int index = random.Next(Start, End+1);

        if (index > End)
        {
            index = Exception;
        }
        return index;
    }
}

In your main program, simply call it

static void Main(string[] args)
    {
        Random random = new Random();

        // Define your ranges
        List<RandomRange> ranges = new List<RandomRange>
        {
            new RandomRange(2, 10, 15), // Represents indices from 2 to 10
            new RandomRange(15, 20, 25), // Represents indices from 15 to 20
            new RandomRange(25, 30, 35) // Represents indices from 25 to 30
        };
        //i use random here in this case, but u can simply change it to a user input
        RandomRange selectedRange = ranges[random.Next(ranges.Count)];
    
        Console.WriteLine($"Selected Index: {selectedRange.getRandomIndex()}");

    }

You can then use the selectedRange.getRandomIndex() to get your list item

Note that there is no check for index out of bound exception and i presume you already done all the list indexing exception handling

I hope the RandomRange class is easy enough

0
Jeroen van Langen On

I would go for a lookup array instead of programming edge-cases.

The reason for this is that when there are edge cases in data handling, you have to see if you can also solve it dynamically. So don't program it in the code. This makes your code less readable and less maintainable. Should (multiple) edge-cases be necessary in the future, you could also save the lookup array as data somewhere (a data-file) and adjust it without having to change the program. (so no recompile is needed)

So, create a lookup array which contains the valid indices. This way you can easily do a normal random on a consecutive array. The selected value is the index you should use on the original array.

Here is an example how I would do it:

public class Program
{
    private static Random _rnd = new Random();

    public static void Main()
    {
        // Some example array containing all the values.
        var myArray = "abcdefghijklmnop".ToArray();

        // The lookup array containing the indices which are valid.
        var rndLookup = new[] { 2, 3, 4, 5, 6, 7, 8, 15 };

        // Choose a random index of the lookup-array and use
        // the length as maximum.
        var rndIndex = _rnd.Next(rndLookup.Length);

        // Select the value from the original array, via the lookup-array.
        // It would be wise to check if there is no index out of bounds
        // On the original array.
        Console.WriteLine("The random value is: " + myArray[ rndLookup[rndIndex] ]);
    }
}