Reputation: 397
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?
Upvotes: 4
Views: 360
Reputation: 9201
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);
Upvotes: 2
Reputation: 63367
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.
Upvotes: 4