使用LINQ从列表中选择多个对象

时间:2014-05-29 15:21:54

标签: c# asp.net-mvc linq

我需要从马匹列表中选择随机对象。目前我正在尝试使用LINQ。我需要做的是用户选择他们想要的对象数量,并从列表中随机选择对象数量。

此处是我的代码:

Random rand = new Random();

//creates a list of horses that haven't yet been assigned to players
List<Horse> unassignedHorses = retrieveUnassignedHorses(); 

List<Horse> selectedHorses = unassignedHorses.OrderBy(m => rand.Next())
    .Take(numberHorses)
    .ToList();

我的问题是这是一个很好的方法,或者是一种更好的方式。

3 个答案:

答案 0 :(得分:4)

当您想从集合中获取&#34; N个随机项时,可以使用两种通用方法。

  1. 选择一个随机项目,检查之前是否已经选择,如果已经选择,请选择一个新项目。
  2. 随机播放整个系列,然后抓住前N个项目。
  3. 您选择第二个选项(尽管您使用了一种低效且有偏见的方法)。

    哪个最好,这取决于。首先,从技术上讲,第一个选项是O(无穷大),因为有可能一遍又一遍地随机选择相同的项目。如果你想谈论平均情况,它将成为一个有效的选择。

    当您想要的项目数量占集合总大小的一小部分时,第一个选项最佳。如果您只想获得1%的收藏品,那么随机选择已经选择的商品的几率非常非常小。

    另一方面,第二个选项,洗牌更好,如果你想要一个百分比的集合中的项目,因为你做同样的工作量,无论你是否想要1项目或全部。如果您只想要集合中1%的项目,那么您最终会浪费一大堆努力来改变您根本不关心的数据。

    现在,我们 想要做的事情是随机抽取集合中的前N个项目,但不会拖延剩余的所有项目。

    有趣的是,这实际上很容易做到。改组列表的一个更优选的方法是从最高索引倒计数到最低值,选择当前索引下面的项目,并将其与当前索引交换。与排序不同,这不会引入偏差,与O(n * log(n))的排序不同,它不是O(n),更好的是,它的超级容易停止部分。所以如果我们实现这个改组算法:

    public static IEnumerable<T> Shuffle<T>(
        this IEnumerable<T> source, Random random)
    {
        var list = source.ToList();
        for (int i = list.Count; i > 0; i--)
        {
            var index = random.Next(i);
            var temp = list[index];
            list[index] = list[i - 1];
            list[i - 1] = temp;
            yield return temp;
        }
    }
    

    我们现在可以将您的解决方案写成:

    var selectedHorses = unasignedHorses.Shuffle(rand).Take(numberHorses);
    

答案 1 :(得分:0)

int numberHorses = 3; //or some user input
Random r = new Random();
List<Horse> unassignedHorses = retriveUnassignedHorses();
List<Horse> assignedHorses = new List<Horse>();
do
{
  int rIint = r.Next(0, unnasignedHorses.Count);
  if(!assignedHorses.Contains(unassignedHorses[rInt]))
  {
    assignedHorses.Add(unassignedHorses[rInt]);
  }
} (while assignedHorses.Count != numberHorses);

就像我在评论中说的那样,如果你现在的方式有效并且对你有意义,那么为什么要改变呢?我还没有尝试过这段代码,但我认为这样的事情可以完成你正在寻找的东西。这可能看起来过于复杂,但这就是我的解决方案似乎如何开始然后我最终简化它们......

答案 2 :(得分:-2)

所以你想从列表中选择随机对象

我想这可能是完成的事情:

int r = rnd.Next(numberHorses.Count);
Horse  selectedHorse  = unnasignedHorses[r];