linq:随机排序

use*_*087 59 c# linq random

如何更改以下代码,每次从数据库中获取50个不同的随机数据?

return (from examQ in idb.Exam_Question_Int_Tbl
      where examQ.Exam_Tbl_ID==exam_id
      select examQ).OrderBy(x=>x.Exam_Tbl_ID).Take(50);
Run Code Online (Sandbox Code Playgroud)

Tim*_*ter 108

http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

return (from examQ in idb.Exam_Question_Int_Tbl
      where examQ.Exam_Tbl_ID==exam_id
      select examQ).OrderBy(x => Guid.NewGuid()).Take(50);
Run Code Online (Sandbox Code Playgroud)

如果这是LINQ-to-SQL,您只需添加一个ORDER BY NEWID()SELECT语句即可.

正如评论所说,使用像Fisher-Yates Shuffle这样的算法可能更好,这里有一个实现:https://stackoverflow.com/a/375446/284240

  • -1 http://blogs.msdn.com/b/ericlippert/archive/2011/01/20/spot-the-defect-bad-comparisons-part-one.aspx.在时间t:A> B是正确的,因为你的`x => Guid.NewGuid()`.在时间t + n:由于你的`x => Guid.NewGuid()`,A <B是真的.排序函数不是为了改变事物而设计的,在最坏的情况下它可能导致无限循环. (9认同)
  • 记住`ORDER BY NEWID()`对于有很多行的表来说会非常慢.如果你考虑它是如何工作的,它会为每一行生成一个随机数,然后对它们进行排序.整个表的排序是*慢*.如果是这种情况,请使用其他策略,例如http://msdn.microsoft.com/en-us/library/cc441928.aspx(记得不要使用`TOP`,在结果上使用`ORDER BY NEWID()`第一行),或使用SQL Server> = 2005中提供的`TABLESAMPLE`子句.该子句使其返回数据的随机页面,因此只触及一部分数据.非常快. (2认同)

tva*_*son 10

收藏有多大?你可以将它们全部选入内存然后选择随机集合吗?如果是这样,那么Shuffle算法在使用Random和OrderBy是一个很好的shuffle算法吗?将是一个不错的选择.

return idb.Exam_Question_Int_Tbl
          .Where( e => e.Exam_Tbl_ID == exam_id )
          .ToList()
          .Shuffle()
          .Take( 50 );
Run Code Online (Sandbox Code Playgroud)

如果没有,那么我建议一个按newid()(SQL Server随机排序)排序的存储过程.我认为没有办法将基于C#中随机数生成器的表达式转换为LINQ to SQL/Entities.


Fro*_*g84 5

如果你也有同样的问题,我也遇到过...

int Limit = 24;
return (from Q in Context.table
where Q.some_key == 1234
select new classDataType() { 
    FirstAttribute = Q.FirstCol,
    SecondAttribute = Q.SecondCol,
    ThirdAttribute = Q.ThirdCol
}).ToList().OrderBy(x => Guid.NewGuid()).Take(Limit).ToList();
Run Code Online (Sandbox Code Playgroud)

在 sql-linq 之后,它需要是一个列表,因此在使用 OrderBy-NewGuid-Method 之前,您可能需要更改为列表:

return (...-SQL-SELECT-LINQ-...)
    .ToList() //****
    .OrderBy(x => Guid.NewGuid()).Take(Limit).ToList();
Run Code Online (Sandbox Code Playgroud)