代码之家  ›  专栏  ›  技术社区  ›  Jobi Joy

获得随机子集合的最优LINQ查询-随机洗牌

  •  42
  • Jobi Joy  · 技术社区  · 15 年前

    7 回复  |  直到 14 年前
        1
  •  41
  •   Scott Mitchell    14 年前

    另一个选项是使用OrderBy和对GUID值进行排序,您可以使用:

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

    我做了一些实证测试,以说服自己上述事实上产生了一个随机分布(似乎是这样)。你可以在网站上看到我的结果 Techniques for Randomly Reordering an Array .

        2
  •  106
  •   LukeH    8 年前

    继mquander的回答和Dan Blanchard的评论之后,下面是一个LINQ友好的扩展方法,它执行 Fisher-Yates-Durstenfeld shuffle :

    // 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];
            }
        }
    }
    
        3
  •  15
  •   user166390 user166390    15 年前

    var r = new Random();
    l.OrderBy(x => r.NextDouble()).Take(n);
    
        4
  •  6
  •   mqp    15 年前

    Shuffle 将集合按随机顺序排列,并取第一个 n 从结果中删除项目。

        5
  •  0
  •   Majid    7 年前

    随机性稍低,但效率较高:

    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);
    
        6
  •  -1
  •   Hernaldo Gonzalez    10 年前

    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();
    
        7
  •  -3
  •   sh1ng    15 年前

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

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