Linq2sql:获得具有权重的随机元素的有效方法? [英] Linq2sql: efficient way to get random elements with weight?

查看:80
本文介绍了Linq2sql:获得具有权重的随机元素的有效方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以说我有一个整数权重,即权重为10的元素的选择概率是权重为1的元素的10倍.

Byt lets say I have an integer weight where i.e. elements with weight 10 has 10 times higher probability to be selected than element with weight 1.

var ws = db.WorkTypes
.Where(e => e.HumanId != null && e.SeoPriority != 0)
.OrderBy(e => /*????*/ * e.SeoPriority)
.Select(e => new
{
   DescriptionText = e.DescriptionText,
   HumanId = e.HumanId
})
.Take(take).ToArray();

当我需要对结果进行加权时,如何解决在Linq中获取随机记录的问题?

How do I solved getting random records in Linq when I need the result to be weighted?

我需要类似 T-SQL中的随机加权选择之类的东西,但在linq不仅获得一项记录?

I need somthing like Random Weighted Choice in T-SQL but in linq and not only getting one record?

如果我没有加权要求,我会使用NEWID方法,可以采用这种方式吗?

If I wouldn't have the weighted requirement, I'd use the NEWID approach, can I adopt this some way?

partial class DataContext
{
    [Function(Name = "NEWID", IsComposable = true)]
    public Guid Random()
    {
        throw new NotImplementedException();
    }
}

...

var ws = db.WorkTypes
.Where(e => e.HumanId != null && e.SeoPriority != 0)
.OrderBy(e => db.Random())
.Select(e => new
{
   DescriptionText = e.DescriptionText,
   HumanId = e.HumanId
})
.Take(take).ToArray();

推荐答案

我的第一个想法与罗恩·克莱因(Ron Klein)的想法相同-创建一个加权列表并从中随机选择.

My first idea was the same as Ron Klein's - create a weighted list and select randomly from that.

这是一种LINQ扩展方法,可以通过已知对象的weight属性的lambda函数从普通列表创建加权列表.

Here's a LINQ extension method to create the weighted list from the normal list, given a lambda function that knows the weight property of the object.

请放心,如果您没有立即获得所有的泛型信息,请按照以下用法进行操作:

Don't worry if you don't get all the generics stuff right away... The usage below should make it clearer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class Item
    {
        public int Weight { get; set; }
        public string Name { get; set; }
    }

    public static class Extensions
    {
        public static IEnumerable<T> Weighted<T>(this IEnumerable<T> list, Func<T, int> weight)
        {
            foreach (T t in list)
                for (int i = 0; i < weight(t); i++)
                    yield return t;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Item> list = new List<Item>();
            list.Add(new Item { Name = "one", Weight = 5 });
            list.Add(new Item { Name = "two", Weight = 1 });

            Random rand = new Random(0);

            list = list.Weighted<Item>(x => x.Weight).ToList();

            for (int i = 0; i < 20; i++)
            {
                int index = rand.Next(list.Count());
                Console.WriteLine(list.ElementAt(index).Name);
            }

            Console.ReadLine();
        }
    }
}

从输出中可以看到,结果是随机的,也可以根据需要加权.

As you can see from the output, the results are both random and weighted as you require.

这篇关于Linq2sql:获得具有权重的随机元素的有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆