C# 是否有一种更有效的方法将一组LINQ结果随机化?

C# 是否有一种更有效的方法将一组LINQ结果随机化?,c#,linq,random,C#,Linq,Random,我已经生成了一个函数,可以根据传递给它的数据量获取一组随机提交的数据,但是我担心,即使现在它可以在传递大量数据时处理少量数据,它也会变得有效并导致问题 有没有一种更有效的方法可以做到以下几点 public List<Submission> GetRandomWinners(int id) { List<Submission> submissions = new List<Submission>(); int am

我已经生成了一个函数,可以根据传递给它的数据量获取一组随机提交的数据,但是我担心,即使现在它可以在传递大量数据时处理少量数据,它也会变得有效并导致问题

有没有一种更有效的方法可以做到以下几点

    public List<Submission> GetRandomWinners(int id)
    {
        List<Submission> submissions = new List<Submission>();
        int amount = (DbContext().Competitions
                     .Where(s => s.CompetitionId == id).FirstOrDefault()).NumberWinners;

        for (int i = 1 ; i <= amount; i++)
        {
            bool added = false;
            while (!added)
            {
                bool found = false;

                var randSubmissions = DbContext().Submissions
                    .Where(s => s.CompetitionId == id && s.CorrectAnswer).ToList();

                int count = randSubmissions.Count();
                int index = new Random().Next(count);

                foreach (var sub in submissions)
                {
                    if (sub == randSubmissions.Skip(index).FirstOrDefault())
                        found = true;
                }

                if (!found)
                {
                    submissions.Add(randSubmissions.Skip(index).FirstOrDefault());
                    added = true;
                }
            }
        }
        return submissions;
    }
公开列表(int-id)
{
列表提交=新列表();
int amount=(DbContext().com)
.其中(s=>s.CompetitionId==id).FirstOrDefault()).NumberInners;
for(int i=1;i s.CompetitionId==id&&s.CorrectAnswer).ToList();
int count=rand.count();
int index=new Random().Next(计数);
foreach(提交文件中的var sub)
{
if(sub==randSubmissions.Skip(index.FirstOrDefault())
发现=真;
}
如果(!找到)
{
submissions.Add(randSubmissions.Skip(index.FirstOrDefault());
添加=真;
}
}
}
返回意见书;
}
正如我所说,我已经充分发挥了作用,并带回了想要的结果。只是我不喜欢<代码>前文和<代码>,在这里检查,我的头刚刚转向MUH,现在试图想出上面的解决方案。

(请阅读所有的方式,因为有不同方面的效率要考虑。)< /P> 确实有更简单的方法可以做到这一点——特别是,您确实不需要重复执行正确答案的查询。为什么要在循环中获取

randSubmissions
?您还应该查看
ElementAt
以避免
Skip
FirstOrDefault
-并记住,由于
randSubmissions
是一个列表,您可以使用正常的列表操作,如
Count
属性和索引器

首先想到的选项是执行部分洗牌。有大量关于堆栈溢出的示例。您可以非常轻松地修改该代码,以避免对整个列表进行洗牌-只需洗牌,直到获得所需的任意多个随机元素。事实上,这些天我可能会以稍微不同的方式实现洗牌,你可以直接调用:

return correctSubmissions.Shuffle(random).Take(amount).ToList();
例如:

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    for (int i = 0; i < elements.Length; i++)
    {
        // Find an item we haven't returned yet
        int swapIndex = i + rng.Next(elements.Length - i);
        T tmp = elements[i];
        yield return elements[swapIndex];
        elements[swapIndex] = tmp;
        // Note that we don't need to copy the value into elements[i],
        // as we'll never use that value again.
    }
}
我相信这将在SQL中使用一个“IN”子句,尽管这样检索条目的数量是有限制的

这样,即使您有100000个正确条目和3个获奖者,您也只能获得100000个ID,但有3个完整记录。希望这有意义

< P>(请阅读全文,因为有不同方面的效率要考虑。)

确实有更简单的方法可以做到这一点——特别是,您确实不需要重复执行正确答案的查询。为什么要在循环中获取
randSubmissions
?您还应该查看
ElementAt
以避免
Skip
FirstOrDefault
-并记住,由于
randSubmissions
是一个列表,您可以使用正常的列表操作,如
Count
属性和索引器

首先想到的选项是执行部分洗牌。有大量关于堆栈溢出的示例。您可以非常轻松地修改该代码,以避免对整个列表进行洗牌-只需洗牌,直到获得所需的任意多个随机元素。事实上,这些天我可能会以稍微不同的方式实现洗牌,你可以直接调用:

return correctSubmissions.Shuffle(random).Take(amount).ToList();
例如:

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    for (int i = 0; i < elements.Length; i++)
    {
        // Find an item we haven't returned yet
        int swapIndex = i + rng.Next(elements.Length - i);
        T tmp = elements[i];
        yield return elements[swapIndex];
        elements[swapIndex] = tmp;
        // Note that we don't need to copy the value into elements[i],
        // as we'll never use that value again.
    }
}
我相信这将在SQL中使用一个“IN”子句,尽管这样检索条目的数量是有限制的

这样,即使您有100000个正确条目和3个获奖者,您也只能获得100000个ID,但有3个完整记录。希望这有意义