【问题标题】:Select Random Items but with some items having a higher percentage of being selected?选择随机项目,但某些项目被选中的百分比更高?
【发布时间】:2017-05-01 12:03:07
【问题描述】:

我正在使用 MVC C# 和 SQL Sever。

我有大约 100 个项目,我从中选择了 2 个随机项目。这是由新的 guid 直接排序。

 vm = vm.OrderBy(c => Guid.NewGuid()).Take(2).ToList();

但现在我希望能够将项目子集标记为具有更高百分比 (20%) 被选中,然后在以后将另一个子集标记为 50%。

项目列表是静态的。它总是大约 100 项。

我只是想暴力破解它并将 20% 以上的选定项目添加到列表中,他们只是随机选择两次。

vm1 = vm.OrderBy(c => Guid.NewGuid()).Take(1).Single();
vm2 = vm.OrderBy(c => Guid.NewGuid()).Where(_ => _.Id != firstSelectedID).Take(1).Single();

但我想在 SQL 中可能有一种更简洁、性能更高的方式,或者我在 C# 中缺少的东西

【问题讨论】:

  • 旁白:Don't use a Guid as a random number generator!。至少改用Random.Next()
  • 这不是随机数生成器。对于这个用例,使用 Guid 和 Sort 是足够随机的。如果我想要真正的随机,我会使用 random.org
  • 好吧,你当然可以忽略Eric Lippert's advice,他说“GUID 保证是唯一的,但不保证是随机的。不要将它们用作随机数。 "
  • 您的项目在数据库中还是在内存中?你想用 sql 查询或在内存中执行此操作就可以了(将加载所有 100 个项目)?
  • 试想一下:从 (1,2,3) 中抽取一个随机元素,每个元素都有 33,33% 的机会。对于 (1,2,3,3),您有 25% 的 (1,2) 和 50% 的 3

标签: c# sql-server random


【解决方案1】:

有一种纯粹的 TSQL 方式可以做到这一点,你可以在 C# 中以同样的方式编写它,但我不确定如何通过 Entity Framework 来实现。

declare @table table ( letter nchar(1), weight int)
insert into @table values ('A', 1)
insert into @table values ('B', 2)
insert into @table values ('C', 3)
insert into @table values ('D', 4)
insert into @table values ('E', 5)

declare @total int;
select @total = sum(weight) from @table

declare @selected int;
set @selected = rand() * @total

select @selected

select top 1  * from (
select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table
) data where runningTotal > @selected order by runningTotal

您将获得 'E' 5 个图块的频率与返回 'A' 的频率相同。这大致基于https://en.wikipedia.org/wiki/Fitness_proportionate_selection 您可以用任何可以给您加权的过程替换权重列。

你可以运行

select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table

并查看数据将如何加权。

以下版本更好,因为它在一次操作中完成所有操作,但我保留了上面的副本,因为它更清楚发生了什么。

select top 1  * from (
select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table
) data where runningTotal > rand() * (select sum(weight) from @table) order by runningTotal

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2011-08-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多