I have a collection contains let say 100 items.
Collection<int> myCollection = new Collection<int>();
for(int i; i <= 100; i++)
{
myCollection .Add(i);
}
How can i randomly select items by percentage(eg. 30%) from this collection?
I have a collection contains let say 100 items.
Collection<int> myCollection = new Collection<int>();
for(int i; i <= 100; i++)
{
myCollection .Add(i);
}
How can i randomly select items by percentage(eg. 30%) from this collection?
Try this:
var rand = new Random();
var top30percent = myCollection.OrderBy(x=> rand.Next(myCollection.Count))
.Take((int)(0.3f*myCollection.Count)).ToList();
You can remove the ToList()
if you want some deferred query.
There's two parts in your question. First, you must shuffle your collection in order to select items randomly. To shuffle it, you can do it properly with the Fisher-Yates shuffle, or just order your items using a pseudo-random generator.
The Fisher-Yates shuffle comes from this popular answer :
public static IList<T> Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
However, I'm returning the list so we can use it cleanly with the take part.
Also, if you don't really need to shuffle cleanly, you can use a simple OrderBy
with either i => random.Next()
or i => Guid.NewGuid()
as the lambda expression.
Secondly, once it's shuffled, now you need to take a percentage of items. You can do this simply by using the Take
LINQ method.
Like the Shuffle method, you can make it as an Extension method :
public static IEnumerable<int> TakePercentage(this IList<int> list, int percentage)
{
return list.Take(percentage * list.Count / 100);
}
If you prefer receiving a decimal (e.g. 0.3) directly :
public static IEnumerable<int> TakePercentage(this IList<int> list, double percentage)
{
return list.Take((int)(percentage * list.Count));
}
Finally, to use it, it's quite simple :
var thirtyPercent = myCollection.Shuffle().Take(30);