[英]Selecting multiple objects from a list using 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();
我的问题是这样做的好方法,还是更好的方法。
当您要获取“来自集合的N个随机项目”时,可以使用两种通用方法。
您选择第二个选项(尽管您使用的是效率低下且有偏见的方法)。
最好,这取决于。 首先,从技术上讲,第一个选项是O(infinity),因为有可能一遍又一遍地随机选择同一项目。 如果您想谈一谈一般情况,那么它就成为一个有效的选择。
当您想要的项目数仅占集合总大小的一小部分时,第一个选项是最佳选择。 如果您只想获取该系列商品的1%,那么随机选择已选商品的几率非常小。
另一方面,如果您要在集合中占很大比例的项目,则改组是更好的选择,因为您要做的是相同数量的工作,而不管是要一个项目还是全部项目。 如果只需要集合中1%的项目,那么最终将浪费大量您根本不在乎的工作量。
现在,我们真正想要做的是随机地重新整理集合的前N个项目,但不重新整理所有剩余的项目。
有趣的是,这实际上很容易做到。 改组列表的一种更可取的方法是从最高索引倒数到最低索引,选择当前索引以下的项目,然后将其与当前索引交换。 与排序不同,这不会引入偏差,与排序不同的是O(n),它不同于O(n * log(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);
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);
就像我在评论中说的那样,如果您的方式现在可以工作并且对您有意义,那么为什么要更改它? 我没有尝试过这段代码,但是我认为这样的事情可以满足您的需求。 它似乎过于复杂,但这就是我的解决方案开始的方式,然后我最终简化了它们。
所以你想从列表中选择随机对象
我想这可以做到:
int r = rnd.Next(numberHorses.Count);
Horse selectedHorse = unnasignedHorses[r];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.