我正在尝试在复杂类型的集合上编写LINQ查询。我想在这个集合上写一个截然不同的查询,以获得两个字段的组合。
我不认为Lambda表达支持Distinct的管道(f => f.propertyname)。希望它做到了。有人使用更简单的实现然后使用Comparer吗?
答案 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());
优点:
缺点:
答案 2 :(得分:0)
你不能使用那样的明显。编译器无法知道要采用多个值中的哪一个。你可以使用GroupBy()来组合它们,或者使用Min(),Max(),First(),Last()或类似的东西来根据你的需要从列表中选择一个。
答案 3 :(得分:0)
您有几种选择:
Distinct
IEqualityComparer<T>
Equals
+ GethashCode
不需要创建新类或修改现有类的另一种(效率较低)方法是使用匿名类型的内置GetHashCode
+ Equals
并{{1 }}:
Enumerable.GroupBy
以下是第二种方法的示例:
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;
}
}
}
- 类({方法)的Equals
和GethashCode
类似。
答案 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));
}
希望这有帮助!