如何使用Linq获取随机对象

时间:2010-07-04 04:27:17

标签: c# .net linq random

我想在linq中获取一个随机对象。我就是这样做的。

//get all the answers
var Answers = q.Skip(1).Take(int.MaxValue);
//get the random number by the number of answers
int intRandomAnswer = r.Next(1, Answers.Count());
int count = 0;

//locate the answer
foreach(var Answer in Answers)
{
    if (count == intRandomAnswer)
    {
        SelectedPost = Answer;
        break;
    }
    count++;
}

这是最好的方法吗?

9 个答案:

答案 0 :(得分:37)

怎么样:

SelectedPost = q.ElementAt(r.Next(1, Answers.Count()));

进一步阅读:

下面的评论对密切相关的问题做出了很好的贡献,我将其纳入此处,因为正如@Rouby指出的那样,搜索这些答案的人可能会找到这个答案,但在这些情况下这些答案是不正确的

整个输入的随机元素

要使所有元素成为随机选择中的候选元素,您需要将输入更改为r.Next

SelectedPost = Answers.ElementAt(r.Next(0, Answers.Count()));

@Zidad添加了一个有用的扩展方法来获取序列中所有元素的随机元素:

public static T Random<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null)
    {
         throw new ArgumentNullException(nameof(enumerable));
    }

    // note: creating a Random instance each call may not be correct for you,
    // consider a thread-safe static instance
    var r = new Random();  
    var list = enumerable as IList<T> ?? enumerable.ToList(); 
    return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)];
}

答案 1 :(得分:9)

使用Fisher-Yates-Durstenfeld shuffle

(您可以使用帮助/扩展程序方法shuffle your IEnumerable<T> sequence。或者,如果您使用的是IList<T>,可以perform an in-place shuffle,如果您愿意的话。)

答案 2 :(得分:8)

另一种古怪的方法(对大型数据集来说效率最高):

SelectedPost = q.OrderBy(qu => Guid.NewGuid()).First();

答案 3 :(得分:4)

var rand = new Random();
var selectedPost = q.Skip(rand.Next(0, q.Count())).Take(1).FirstOrDefault();

最理想的情况是,您只想对单个值进行函数查询,因此您设置Skip / Take跳转到与您生成的随机数匹配的序列号(由数据集的itemcount限制,因此基于MAX(pkey)的缺失行问题边界不是问题)然后在序列中的那一点抓住第一个项目。

在SQL中,这与查询SELECT Count(*) FROM q相同,然后SELECT * FROM q LIMIT {0}, 1 {0}rand.Next(0, count),这应该非常有效。

答案 4 :(得分:4)

基于接受的答案的通用扩展方法(它不总是跳过第一个,只枚举可枚举一次):

 public static class EnumerableExtensions
    {
        public static T Random<T>(this IEnumerable<T> enumerable)
        {
            var r = new Random();
            var list = enumerable as IList<T> ?? enumerable.ToList();
            return list.ElementAt(r.Next(0, list.Count()));
        }
    }

答案 5 :(得分:2)

派对迟到了,但这是谷歌的一个高涨结果。一个简洁的版本可能是:

var rnd = new Random();
var SelectedPost = q.OrderBy(x => rnd.Next()).Take(1);

它的缺点是它会向所有元素应用一个随机数,但它是紧凑的,可以很容易地修改为多个随机元素。

答案 6 :(得分:1)

从数据库移动大量数据时,拉出所有答案并循环它们并不是最有效的方法。如果您使用的是自动递增的整数主键,则应获取主键的Max,然后在该范围内找到随机整数。然后根据从随机函数派生的主键直接获得单个答案。

答案 7 :(得分:1)

我发布了一个答案,因为我没有足够的声誉来发表评论。

我喜欢这个答案:

SelectedPost = q.ElementAt(r.Next(1, Answers.Count()));

ElementAt基于零,肯定从1开始,然后转到Answers.Count(),你最终可能会超出范围,你永远不会得到第一个实体。< / p>

岂不

SelectedPost = q.ElementAt(r.Next(0, Answers.Count() - 1));

更好吗?

答案 8 :(得分:0)

我在数据库中有产品表,每次用户输入一个产品详细信息我想在页面下方显示10个类似的产品。在每次刷新时,此列表必须更改。必须随机出现。

Linq看起来像这样

var products =
            DataContextFactory.GetDataContext()
                .Set<Product>()
                .Where(x =>x.Id!=id)
                .OrderBy(emp => Guid.NewGuid())
                .Take(10).ToList();

x.Id!=id 

这仅适用于未将所选产品列入清单。

完美无缺