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();
How do I solved getting random records in Linq when I need the result to be weighted?
I need somthing like Random Weighted Choice in T-SQL but in linq and not only getting one record?
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();
My first idea was the same as Ron Klein's - create a weighted list and select randomly from that.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With