基于数据的加权随机选择

时间:2015-12-25 23:28:49

标签: c#

我有一个现有的Windows应用程序,它会在设置的时间间隔内在屏幕上显示一条消息。从SQL Server数据库中随机选择消息,通过使用当前日期标记消息,确保每条消息仅在当天显示一次。表结构如下:

Id int
Text nvarchar
LastDateUsed datetime

我希望通过制作选择消息的逻辑来改进现有代码,以便最近使用过的消息不太可能被选中。

我现有的随机选择邮件的代码如下:

IQueryable<Message> filteredMessages = db.Messages;

var currentDate = DateTime.Today;
IQueryable<int> filteredMessageIds = filteredMessages.Where(x => x.LastDateUsed < currentDate).Select(x => x.Id);
int filteredMessagesCount = filteredMessageIds.Count();

// Select one Id
int selectedId = filteredMessageIds.ToList()[SelectRandomIndex(filteredMessagesCount)];

// Display selected message
DisplayMessage(selectedId)


private static int SelectRandomIndex(int filteredMessagesCount)
{
    Random rnd = new Random();
    int selectedIndex = rnd.Next(1, filteredMessagesCount - 1);

    return selectedIndex;
}

1 个答案:

答案 0 :(得分:1)

只要消息的数量和上次显示的天数不是太高,这段代码就可以了:

Random rnd = new Random();
int selectedId =
    db
        .Messages
        .Where(x => x.LastDateUsed < DateTime.Today)
        .Select(x => new { x.Id, x.LastDateUsed })
        .ToArray()
        .SelectMany(x =>
            Enumerable.Repeat(x.Id, DateTime.Today.Subtract(x.LastDateUsed).Days))
        .OrderBy(x => rnd.Next())
        .Concat(new [] { -1 })
        .First();

此代码的主要部分是.SelectMany(...)。它会根据上次使用该消息后的天数为每条消息重复Id。因此,7天前最后一次使用的消息有7倍的机会被选中一天前使用的消息。

OrderBy有点浪费,你需要检查-1是否没有消息,但它应该没问题。