Python’s module ‘random’ has a function random.choice
random.choice(seq)
Return a random element from the non-empty sequence seq. Ifseqis empty, raisesIndexError.
How can I emulate this in .NET ?
public T RandomChoice<T> (IEnumerable<T> source)
Edit: I heard this as an interview question some years ago, but today the problem occurred naturally in my work. The interview question was stated with constraints
- ‘the sequence is too long to save to memory’
- ‘you can only loop over the sequence once’
- ‘the sequence doesn’t have a length/count method’ (à la .NET IEnumerable)
To make a method that iterates the source only once, and doesn’t have to allocate memory to store it temporarily, you count how many items you have iterated, and determine the probability that the current item should be the result:
When you are at the first item, the probability is 1/1 that it should be used (as that is the only item that you have seen this far). When you are at the second item, the probability is 1/2 that it should replace the first item, and so on.
This will naturally use a bit more CPU, as it creates one random number per item, not just a single random number to select an item, as dasblinkenlight pointed out. You can check if the source implements
IList<T>, as Dan Tao suggested, and use an implementation that uses the capabilities to get the length of the collection and access items by index:Note: You should consider sending the
Randominstance into the method. Otherwise you will get the same random seed if you call the method two times too close in time, as the seed is created from the current time.The result of a test run, picking one number from an array containing 0 – 9, 1000000 times, to show that the distribution of the chosen numbers is not skewed: