按百分比从ASP.NET集合中选择项目

4
我有一个包含100个项目的集合。
Collection<int> myCollection = new Collection<int>();

for(int i; i <= 100; i++)
{
    myCollection .Add(i);
}

我该如何从这个集合中按比例(例如30%)随机选择项目?
2个回答

4

试试这个:

var rand = new Random();
var top30percent = myCollection.OrderBy(x=> rand.Next(myCollection.Count))
                               .Take((int)(0.3f*myCollection.Count)).ToList();

如果您想要一些延迟查询,您可以删除ToList()

我真的很喜欢这个答案 +1。 - Tarik
唯一的问题是可能会选择同一项超过一次。这取决于操作者的需求,这可能是可以接受的,也可能不可接受。 - Icemanind
不错!是的,我需要避免同一项被选择超过一次。 - My2ndLovE

2

你的问题有两个部分。首先,你必须对你的集合进行洗牌,以便随机选择项目。要进行洗牌,你可以使用 Fisher-Yates 洗牌算法来正确地进行,或者使用伪随机生成器来对你的项目进行排序。

Fisher-Yates 洗牌算法来源于这个流行答案

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;
}

然而,我返回列表以便我们可以在参与过程中干净地使用它。此外,如果您不需要干净地洗牌,则可以使用一个简单的OrderByi => random.Next()i => Guid.NewGuid()作为lambda表达式。
其次,一旦它被洗牌,现在您需要取一定比例的项目。您可以通过使用Take LINQ方法来轻松完成此操作。
像Shuffle方法一样,您可以将其制作为扩展方法:
public static IEnumerable<int> TakePercentage(this IList<int> list, int percentage)
{
    return list.Take(percentage * list.Count / 100);
} 

如果您希望直接获得十进制数值(例如0.3):
public static IEnumerable<int> TakePercentage(this IList<int> list, double percentage)
{
    return list.Take((int)(percentage * list.Count));
} 

最后,要使用它非常简单:
var thirtyPercent = myCollection.Shuffle().Take(30);

不错。但是同样的项目会被选择多次,对吧? - My2ndLovE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接