查找未一起查看的两个元素的组合(LINQ、SQL 或 C#)
我有一个页面显示两个对象,然后用户选择其中之一。 我将偏好和组合记录在 MSSQL 数据库中,并最终存储如下数据:
UserId=1, BetterObjectId=1, WorseObjectId=2
现在我想避免再次显示对象的组合 (1,2 / 2,1)。
那么我如何生成随机组合来向用户显示排除以前查看过的组合?
这似乎应该是一个非常简单的问题,但像大多数程序员一样,我睡眠不足和咖啡,所以非常感谢您的帮助:-)
非常天真的方法是这样的(并且对此函数的所有调用都必须包含在检查中,以查看用户是否已经评级为多次作为 nCr,其中 n 是项目计数,r 是 2):
public List<Item> GetTwoRandomItems(int userId)
{
Item i = null, i2 = null;
List<Item> r = null;
while (i == null || i2 == null)
{
r = GetTwoRandomItemsRaw();
i = r[0];
i2 = r[1];
if (GetRating(i.Id, i2.Id, userId) != null) /* Checks if viewed */
{
i = null;
i2 = null;
}
}
return r;
}
private List<Item> GetTwoRandomItemsRaw()
{
return Items.ToList().OrderBy(i => Guid.NewGuid()).Take(2).ToList();
}
编辑
使用一些 SQL,我可以生成所有不完整项目的列表(即,存在涉及以下项目的组合)用户没有见过)但我认为不是特别有用。
我还可以想象在选择 2 个随机项目之前生成所有可能的组合并消除已经查看过的组合,但这是另一个糟糕的解决方案。
一种可能性(对于大 n 来说是内存密集型)是生成所有可能的组合并将combinationId 存储在评级中。 然后,我可以对所有组合进行 SELECT,其中combinationId IS NOT IN (SELECTcombinationId FROM ratings WHERE userId=x),并进行一些更改以反映组合的对称关系。
I have a page that displays two objects and then the user picks one of these. I record the preference and the combination in a MSSQL database and end up storing data like this:
UserId=1, BetterObjectId=1, WorseObjectId=2
Now I would like to avoid showing that combination of objects (1,2 / 2,1) ever again.
So how do I generate random combinations to show the user excluding previously viewed combinations?
This seems like it should be a really straightforward question but like most programmers I'm short on sleep and coffee so your help is much appreciated :-)
The very naive approach is something like this (and all calls to this function would have to be wrapped in a check to see if the user has already rated as many times as nCr where n is the item count and r is 2):
public List<Item> GetTwoRandomItems(int userId)
{
Item i = null, i2 = null;
List<Item> r = null;
while (i == null || i2 == null)
{
r = GetTwoRandomItemsRaw();
i = r[0];
i2 = r[1];
if (GetRating(i.Id, i2.Id, userId) != null) /* Checks if viewed */
{
i = null;
i2 = null;
}
}
return r;
}
private List<Item> GetTwoRandomItemsRaw()
{
return Items.ToList().OrderBy(i => Guid.NewGuid()).Take(2).ToList();
}
Edits
Using some SQL I can generate a list of all items that aren't complete (i.e. there is a combination involving the item that the user hasn't seen) but I don't think is particularly useful.
I can also imagine generating every possible combination and eliminating already viewed ones before picking 2 random items but this is a another terrible solution.
A possibility (memory intensive for large n) is to generate all possible combinations and store the combinationId in the rating. Then I can just do a SELECT of all combinations WHERE combinationId IS NOT IN (SELECT combinationId FROM ratings WHERE userId=x) with some changes to reflect the symmetric relationship of combinations.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您要求 ItemId1 < 评分表中的 ItemId2,您只需检查一次评分表。
这是一个博客 关于将“随机”翻译到数据库中。
If you require that ItemId1 < ItemId2 in the Rating table, you only have to check the Rating table once.
Here's a blog about getting "random" translated into the database.
一种解决方案是:
我不知道 交叉连接之前只是列出多个FROM表的方法。
One solution is this:
I wasn't aware of the cross join method of just listing multiple FROM tables before.
假设可用项目列表在数据库中,我将完全在数据库中处理这个问题。 无论如何,您已经在访问数据库了,那么为什么不在那里完成它呢?
Assuming that the list of available items is in the database, I would handle this problem entirely in the database. You are hitting the database already, no matter what, so why not get it done there?
将所有对象放入队列或堆栈中,然后将 2 和 2 弹出,直到它们为空怎么样?
What about putting all the objects in a queue or a stack, and then pop 2 and 2 off until they are empty?