c# - 查找未一起查看的两个元素的组合(LINQ、SQL 或 C#)

标签 c# sql linq linq-to-sql combinations

我有一个显示两个对象的页面,然后用户选择其中一个。我将首选项和组合记录在 MSSQL 数据库中,并最终像这样存储数据:

UserId=1, BetterObjectId=1, WorseObjectId=2

现在我想避免再次显示对象组合 (1,2/2,1)。

那么我如何生成随机组合以向用户显示排除之前查看过的组合?

这看起来应该是一个非常简单的问题,但像大多数程序员一样,我缺乏 sleep 和咖啡,所以非常感谢您的帮助:-)

非常 天真的方法是这样的(并且必须将对此函数的所有调用包装在一个检查中,以查看用户是否已经评价了与 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 WHERE combinationId IS NOT IN (SELECT combinationId FROM ratings WHERE userId=x) 并进行一些更改以反射(reflect)组合的对称关系。

最佳答案

Table Item: ItemId
Table Rating: UserId, ItemId1, ItemId2, WinnerId

如果你要求Rating表中的ItemId1 < ItemId2,你只需要检查一次Rating表。

var pair = db.Items.Join(db.Items,
  i1 => i1.ItemId,
  i2 => i2.ItemId,
  (i1, i2) => new {i1, i2}
)  //produce all pairs
.Where(x => x.i1.ItemId < x.i2.ItemId) //filter diagonal to unique pairs
.Where(x => 
  !db.Ratings
  .Where(r => r.UserId == userId
    && r.ItemId1 == x.i1.ItemId
    && r.ItemId2 == x.i2.ItemId)
  .Any() //not any ratings for this user and pair
)
.OrderBy(x => db.GetNewId()) //in-database random ordering
.First();  // just give me the first one

return new List<Item>() {pair.i1, pair.i2 };

这是一个 blog关于将“随机”翻译成数据库。

关于c# - 查找未一起查看的两个元素的组合(LINQ、SQL 或 C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/601134/

相关文章:

c# - 在 LINQ To ActiveDirecory 中检测到 DisconnectedContext

c# - 缺少 App1.Pages.SetPageDetail 的默认构造函数(位置 12 :18)

c# - 如何使用 lambda 表达式从两个集合中返回一个字段

c# - 在 CUDAfy 中的结构内传递数组

sql - 在postgresql中将日期转换为整数

sql - 没有主键的多对多

mysql - 如何将两列合并为具有最高 ID 的一列?

c# - 如何在运行时查找窗体中的所有控件

c# - 是否可以在 C#/LINQ 中扩展查询关键字?

c# - LINQ & IEnumerable<String> 重新求值