如何将此逻辑转换为LINQ语句?

时间:2010-05-29 20:58:46

标签: linq

我无法将这一点逻辑转换为Linq语句,这让我疯狂。我有一个包含类别和createdondate字段的项目列表。我希望按类别进行分组,只返回具有其类别的最大日期的项目。

因此,例如,列表包含具有类别1和2的项目。第一天(1/1)我将两个项目发布到类别1和2.第二天(1/2)我将三个项目发布到类别1.该列表应将第二天的帖子返回到第1类,将第一天的帖子返回到第2类。

现在我按类别进行分组,然后运行foreach循环,将组中的每个项目与组的最大日期进行比较,如果日期小于删除项目的最大日期。

必须有一种方法来解决这个问题,但我还没想到它!

3 个答案:

答案 0 :(得分:2)

你可以这样做:

    from item in list
    group item by item.Category into g
    select g.OrderByDescending(it => it.CreationDate).First();

但是,它效率不高,因为它需要对每个组的项进行排序,这比必要的更复杂(您实际上不需要排序,只需要扫描列表一次)。所以我创建了这个扩展方法来查找具有属性(或函数)的最大值的项:

    public static T WithMax<T, TValue>(this IEnumerable<T> source, Func<T, TValue> selector)
    {
        var max = default(TValue);
        var withMax = default(T);
        var comparer = Comparer<TValue>.Default;
        bool first = true;
        foreach (var item in source)
        {
            var value = selector(item);
            int compare = comparer.Compare(value, max);

            if (compare > 0 || first)
            {
                max = value;
                withMax = item;
            }
            first = false;
        }
        return withMax;
    }

您可以按如下方式使用它:

    from item in list
    group item by item.Category into g
    select g.WithMax(it => it.CreationDate);

更新:正如安东尼在评论中指出的那样,这段代码并没有完全回答这个问题...如果你想要所有项目的日期是他们类别的最大值,你可以这样做:

    from item in list
    group item by item.Category into g
    let maxDate = g.Max(it => it.CreationDate)
    select new
    {
        Category = g.Key,
        Items = g.Where(it => it.CreationDate == maxDate)
    };

答案 1 :(得分:1)

这个怎么样:

    private class Test
    {
        public string Category { get; set; }
        public DateTime PostDate { get; set; }
        public string Post { get; set; }
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        List<Test> test = new List<Test>();
        test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 5, 12, 0, 0), Post = "A1" });
        test.Add(new Test() { Category = "B", PostDate = new DateTime(2010, 5, 5, 13, 0, 0), Post = "B1" });

        test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 12, 0, 0), Post = "A2" });
        test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 13, 0, 0), Post = "A3" });
        test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 14, 0, 0), Post = "A4" });

        var q = test.GroupBy(t => t.Category).Select(g => new { grp = g, max = g.Max(t2 => t2.PostDate).Date }).SelectMany(x => x.grp.Where(t => t.PostDate >= x.max));
    }

答案 2 :(得分:0)

重新格式化luc对查询理解形式的出色答案。我更喜欢这种查询,因为范围规则让我写得更简洁。

  from item in source
  group item by item.Category into g
  let max = g.Max(item2 => item2.PostDate).Date
  from item3 in g
  where item3.PostDate.Date == max
  select item3;