我需要从列表中获取一个随机元素(这不是列表中的两个值)。以下工作正常:
Company dest = companies
.Where(cpy => cpy != src && cpy != plyr.PowerUpInAction.Passenger.Destination)
.OrderBy(pu => rand.Next())
.ToList()[0];
有更好(即更有效)的方法吗?转换为列表会让我感到额外的工作。
谢谢 - 戴夫
答案 0 :(得分:3)
您可以.First()
代替.ToList()[0]
答案 1 :(得分:1)
接受的答案非常好,但我会使用.FirstOrDefault()
代替First()
。
原因是.First()
如果没有找到行,则抛出异常(ArgumentNullException)。这个
意味着你的代码将被停止。你必须添加一个额外的try-catch来处理这个问题。
.FirstOrDefault()
将返回一个null对象(在您的情况下是一个空的Company对象),它根本不会造成任何损坏。您不必添加任何try-catch,也不必在代码中添加null验证。
如果您的公司桌子出于某种原因需要为空,请保存以添加更多代码和未来损坏。这是维护的观点。
答案 2 :(得分:0)
重试,直到找到可接受的元素。这可能是因为只有两个项目被过滤掉了。在最好(可能)的情况下,我们只需一次尝试即可完成。那是O(1)
。
int retryCount = 0;
while (retryCount < 5) {
var index = GetRandomIndex(list.Count);
if (list[index].IsNotFilteredOut)
return list[index];
else
retryCount++;
}
//the fast, probabilistic algorithm has failed. fallback:
return companies.Where(cpy => cpy != src && cpy != plyr.PowerUpInAction.Passenger.Destination).OrderBy(pu => rand.Next()).ToList()[0];
如果我们经常旋转,我们会回到安全算法。
答案 3 :(得分:0)
另一种可能性:
var items = companies.Where( cpy => cpy != src && cpy != plyr.PowerUpInAction.Passenger.Destination );
Company dest = items.First();
int min = int.MaxValue;
foreach( var company in items )
{
int r = rand.Next();
if( r < min )
{
min = r;
dest = company;
}
}
这可以避免对整个列表进行排序以及构建新列表。它仍然是列表大小的线性(因为我们必须评估哪些元素是有效的)。