我有一个班级列表
public class LinqTest
{
public int id { get; set; }
public string value { get; set; }
}
List<LinqTest> myList = new List<LinqTest>();
myList.Add(new LinqTest() { id = 1, value = "a" });
myList.Add(new LinqTest() { id = 1, value = "b" });
myList.Add(new LinqTest() { id = 2, value = "c" });
我只需从该列表中选择不同的ID。 即,我的结果列表应该只包含
[{id=1,value="a"},{ id = 2, value = "c" }]
如何使用linq执行此操作?
修改
输入,
id value
1 a
1 b
2 c
3 d
3 e
输出应该是,
id value
1 a
2 c
3 d
即,如果重复id
,结果应该只出现第一次。
答案 0 :(得分:454)
myList.GroupBy(test => test.id)
.Select(grp => grp.First());
编辑:将IEnumerable<>
变成List<>
对许多人来说似乎是一个谜,你可以简单地写一下:
var result = myList.GroupBy(test => test.id)
.Select(grp => grp.First())
.ToList();
但是最好不要使用IEnumerable
而不是IList
,因为上面的Linq被懒惰地评估了:在重复枚举之前,它实际上并没有完成所有的工作。当你致电ToList
时,它实际上走了整个可枚举的强制,迫使所有的工作都提前完成。 (如果你的数字可以无限长,可能需要一段时间。)
这个建议的另一面是每次枚举这样的IEnumerable
时,必须重新完成评估它的工作。因此,您需要针对每种情况决定是否更好地使用延迟评估的IEnumerable
或将其实现为List
,Set
,Dictionary
或诸如此类。< / p>
答案 1 :(得分:104)
使用morelinq,您可以使用DistinctBy
:
myList.DistinctBy(x => x.id);
否则,您可以使用组:
myList.GroupBy(x => x.id)
.Select(g => g.First());
答案 2 :(得分:52)
您应该有意义地覆盖Equals
和GetHashCode
,在这种情况下要比较ID:
public class LinqTest
{
public int id { get; set; }
public string value { get; set; }
public override bool Equals(object obj)
{
LinqTest obj2 = obj as LinqTest;
if (obj2 == null) return false;
return id == obj2.id;
}
public override int GetHashCode()
{
return id;
}
}
现在您可以使用Distinct
:
List<LinqTest> uniqueIDs = myList.Distinct().ToList();
答案 3 :(得分:23)
myList.GroupBy(i => i.id).Select(group => group.First())