C#LINQ Distinct(f =&; f.property name)不起作用

时间:2014-03-13 08:34:21

标签: c# linq distinct

我正在尝试在复杂类型的集合上编写LINQ查询。我想在这个集合上写一个截然不同的查询,以获得两个字段的组合。

我不认为Lambda表达支持Distinct的管道(f => f.propertyname)。希望它做到了。有人使用更简单的实现然后使用Comparer吗?

5 个答案:

答案 0 :(得分:5)

您可以在MoreLINQ包中使用DistinctBy方法。

var result = items.DistinctBy(f => f.PropertyName);

您可以使用匿名类型进行区分,以便通过两列获得不同的结果。

var result = items.DistinctBy(f => new { f.Property1, f.Property2});

答案 1 :(得分:1)

使用纯LINQ,您可以按所需的所有属性进行分组,然后从每个组中选择第一项:

var result = items.GroupBy(i => new { i.Prop1, i.Prop2 })
                  .Select(g => g.First());

优点:

  • 您不需要创建自定义比较器,或修改您的课程或参考第三方库。
  • 如果您要查询数据库中的项目
  • ,它可以转换为SQL并在服务器端执行

缺点:

  • 使用Linq to Objects MoreLINQ方法更有效(尽管你不应该过早优化)
  • MoreLINQ语法更具表现力

答案 2 :(得分:0)

你不能使用那样的明显。编译器无法知道要采用多个值中的哪一个。你可以使用GroupBy()来组合它们,或者使用Min(),Max(),First(),Last()或类似的东西来根据你的需要从列表中选择一个。

答案 3 :(得分:0)

您有几种选择:

  1. 您可以为Distinct
  2. 的重载实施自定义IEqualityComparer<T>
  3. 或覆盖您班级中的Equals + GethashCode
  4. 不需要创建新类或修改现有类的另一种(效率较低)方法是使用匿名类型的内置GetHashCode + Equals并{{1 }}:

    Enumerable.GroupBy
  5. 以下是第二种方法的示例:

    IEnumerable<Complex> distinctObjects = 
        from c in collection
        group c by  new { c.Prop1, c.Prop2 } into g 
        select g.First(); // change logic if you don't want an arbitrary object(first)
    

    public class Complex { public string Prop1 { get; set; } public int Prop2 { get; set; } public Complex Prop3 { get; set; } public override bool Equals(object obj) { Complex c2 = obj as Complex; if (obj == null) return false; return Prop1 == c2.Prop1 && Prop2 == c2.Prop2; } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; hash = hash * 23 + Prop1.GetHashCode(); hash = hash * 23 + Prop2; return hash; } } } - 类({方法)的EqualsGethashCode类似。

答案 4 :(得分:-2)

您可以使用两个属性动态创建匿名类型,然后使用distinct。

像这样:

[Test]
public void Distinct_with_anonymous_type()
{
    var items = new[]
    {
        new {p1 = 'a', p2 = 2, p3=10},   // double over p1 and p2
        new {p1 = 'a', p2 = 3, p3=11}, 
        new {p1 = 'a', p2 = 2, p3=12},   // double over p1 and p2
    };

    var expected = new[]
    {
        new {p1 = 'a', p2 = 2},
        new {p1 = 'a', p2 = 3}, 
    };

    var distinct = items.Select(itm => new { itm.p1, itm.p2 }).Distinct();

    Assert.That(distinct, Is.EquivalentTo(expected));
}

希望这有帮助!

相关问题