最佳的LINQ查询来获得一个随机的子集合 – 随机播放

请build议一个最简单的方法,从具有“N”个项目的集合中随机抽取“n”个数。 其中n <= N

另一种select是使用OrderBy并对GUID值进行sorting,您可以使用它:

var result = sequence.OrderBy(elem => Guid.NewGuid()); 

我做了一些经验性的testing来说服自己,上面实际上产生了一个随机分布(似乎是这样做的)。 您可以在随机重新sorting数组的技巧中看到我的结果。

除了mquander的回答和Dan Blanchard的评论之外,这里还有一个LINQ友好的扩展方法,执行一个Fisher-Yates-Durstenfeld混洗 :

 // take n random items from yourCollection var randomItems = yourCollection.Shuffle().Take(n); // ... public static class EnumerableExtensions { public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source) { return source.Shuffle(new Random()); } public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng) { if (source == null) throw new ArgumentNullException("source"); if (rng == null) throw new ArgumentNullException("rng"); return source.ShuffleIterator(rng); } private static IEnumerable<T> ShuffleIterator<T>( this IEnumerable<T> source, Random rng) { var buffer = source.ToList(); for (int i = 0; i < buffer.Count; i++) { int j = rng.Next(i, buffer.Count); yield return buffer[j]; buffer[j] = buffer[i]; } } } 

这与“随机偏见”有一些问题,我相信这不是最佳的,这是另一种可能性:

 var r = new Random(); l.OrderBy(x => r.NextDouble()).Take(n); 

将收集顺序随机排列,并从结果中取前n项。

less一点随机,但有效率:

 var rnd = new Random(); var toSkip = list.Count()-n; if (toSkip > 0) toSkip = rnd.Next(toSkip); else toSkip=0; var randomlySelectedSequence = list.Skip(toSkip).Take(n); 

我写这个覆盖的方法:

 public static IEnumerable<T> Randomize<T>(this IEnumerable<T> items) where T : class { int max = items.Count(); var secuencia = Enumerable.Range(1, max).OrderBy(n => n * n * (new Random()).Next()); return ListOrder<T>(items, secuencia.ToArray()); } private static IEnumerable<T> ListOrder<T>(IEnumerable<T> items, int[] secuencia) where T : class { List<T> newList = new List<T>(); int count = 0; foreach (var seed in count > 0 ? secuencia.Skip(1) : secuencia.Skip(0)) { newList.Add(items.ElementAt(seed - 1)); count++; } return newList.AsEnumerable<T>(); } 

然后,我有我的源列表(所有项目)

 var listSource = p.Session.QueryOver<Listado>(() => pl) .Where(...); 

最后,我称之为“随机”,我得到一个随机的子项目集合,在我的情况下,5个项目:

 var SubCollection = Randomize(listSource.List()).Take(5).ToList(); 

对不起,难看的代码:-),但

var result =yourCollection.OrderBy(p => (p.GetHashCode().ToString() + Guid.NewGuid().ToString()).GetHashCode()).Take(n);
var result =yourCollection.OrderBy(p => (p.GetHashCode().ToString() + Guid.NewGuid().ToString()).GetHashCode()).Take(n);