Linq,获取按字段分组的不同元素

时间:2011-08-11 20:46:36

标签: linq c#-4.0

我感到愚蠢,但我不得不承认,我需要你帮助的人似乎很容易找到合适的答案情况

 public class Foo
 {
     public string Name { get; set; }
     public string Time { get; set; }

     public Foo(string name, string time)
     {
        Name = name;
        Time = time;
     }
 }

var o = new List<Foo>
                  {
                      new Foo("Breakfast","9:00"),
                      new Foo("Lunch", "12:00"),
                      new Foo("Breakfast", "8:00")
                  };

如何在9:00和午餐时享用早餐,而不包括8点的早餐?

我开始是这样的:

var a = o.GroupBy(x => x.Name);

但它只会给你名字,我也需要时间。

3 个答案:

答案 0 :(得分:5)

var a = o.GroupBy(x => x.Name).Select(g => g.First())

但想想那个.First()调用。如果有多个元素,您希望如何选择正确的元素 - 您可能希望对元素进行排序以获得最新/最早的元素,或者您的要求是什么。

答案 1 :(得分:3)

一个选项是:

var a = o.GroupBy(x => x.Name)
         .Select(g => g.First());

或者您可以使用DistinctBy中的MoreLINQ

var a = o.DistinctBy(x => x.Name);

后者在内存中效率更高,并且会立即开始产生结果,而第一种方法必须先读取 all 数据才能返回任何内容。另一方面,后者需要MoreLINQ(或复制代码)。

编辑:这里我假设 LINQ to Objects(因为MoreLINQ当然不会与其他提供商合作),并且您对代表该组的任何组的第一次出现感到满意

答案 2 :(得分:0)

为什么不像以下那样? (我也冒昧地让你的代码变得更小 - 我认为既然你的属性是公共的,你不需要构造函数,但只能使用object-initializer语法。这应该都在LinqPad中运行:

void Main() {
    var os = new [] {
        new Foo{Name="Breakfast",Time="9:00"},
        new Foo{Name="Lunch", Time="12:00"},
        new Foo{Name="Breakfast", Time="8:00"}
    };

    os.Where(o => DateTime.Parse(o.Time).Hour > 8).Dump();
}

public class Foo
{
    public string Name { get; set; }
    public string Time { get; set; }
}