3

我有一个查询:

var q = (
    from c in db.tblStoreRecommendations
    where
    itemIDsInCart.Contains(c.ItemID)
    && !itemIDsInCart.Contains(c.RecommendItemID)
    select c
);

它将返回以下内容:

ID    ItemID    RecommendItemID    Message
------------------------------------------
1     25        3                  Msg here
2     26        3                  Something else
3     27        8                  Another message

我需要查询过滤掉具有相同的结果RecommendItemID,这不应该多次出现在返回的结果中。

如果存在两个,它可以使用任何一个(最好随机选择)。所以返回的结果应该省略记录 ID 1 或 2。

谁能告诉我如何做到这一点?谢谢!

4

3 回答 3

6

一种方法是使用 GroupBy,然后从每个组中选择第一项:

var q = (
    from c in db.tblStoreRecommendations
    where
        itemIDsInCart.Contains(c.ItemID)
     && !itemIDsInCart.Contains(c.RecommendItemID)
    select c
).GroupBy(c => c.RecommendItemID)
 .Select(g => g.First());

如果您使用它来显示随机评论,我建议将其强加到使用代码而不是 LINQ 查询中,通过省略First类似这样:

var q = (
    from c in db.tblStoreRecommendations
    where
        itemIDsInCart.Contains(c.ItemID)
     && !itemIDsInCart.Contains(c.RecommendItemID)
    select c
).GroupBy(c => c.RecommendItemID)
 .Select(g => g.ToArray());

var random = new Random();
foreach (var r in q)
{
    var rec = r[random.Next(r.Length)];
    // use your recommendation
}
于 2012-07-16T20:31:15.940 回答
3

我相信您可以在 linq 表达式的末尾添加一个独特的比较,例如:

var q = (
  from c in db.tblStoreRecommendations
  where
  itemIDsInCart.Contains(c.ItemID)
  && !itemIDsInCart.Contains(c.RecommendItemID)
  select c
)
.Distinct((x, y) => x.RecommendItemID == y.RecommendItemID);

编辑

我刚刚意识到我是使用我自己编写的扩展方法来做到这一点的,并且通常可以方便地使用......这是它的代码:

    /// <summary>
    /// Provides a way to get a distinct list of items based on a lambda comparison operator.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source"></param>
    /// <param name="equalityComparer">A comparison function that returns true of the two items are considered equal.</param>
    /// <returns>The list of distinct items.</returns>
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> equalityComparer)
    {
        var distincts = new List<T>();
        foreach (var item in source)
        {
            var found = false;
            foreach (var d in distincts)
            {
                found = equalityComparer(item, d);
                if (found)
                    break;
            }

            if (!found)
            {
                distincts.Add(item);
                yield return item;
            }
        }
    }
于 2012-07-16T20:31:16.597 回答
1

让我们尝试尽可能地坚持查询表达式:

var q = from c in db.tblStoreRecommendations
        where itemIDsInCart.Contains(c.ItemID)
          && !itemIDsInCart.Contains(c.RecommendItemID)
        group c by c.RecommendItemID into matches
        select matches.First();

上下文关键字into在这里肯定会派上用场。

这是随机化它的方法:

private static Random random = new Random();

var q = from c in db.tblStoreRecommendations
        where itemIDsInCart.Contains(c.ItemID)
          && !itemIDsInCart.Contains(c.RecommendItemID)
        group c by c.RecommendItemID
        into matches
        select matches.AsEnumerable().ElementAt(random.Next(matches.Count()));

由于 LINQ to SQL 无法处理调用,因此我在从分组中选择 Random 元素之前ElementAt编辑了执行查询的答案(通过调用)。AsEnumerable

于 2012-07-16T20:48:16.243 回答