我有一个这样的数据列表:
Prod1: Id=1, Name="Book", Active=true
Prod2: Id=2, Name="Book", Active=false
Prod3: Id=3, Name="Book", Active=true
Prod4: Id=4, Name="Laptop", Active=true
Prod5: Id=5, Name="Laptop", Active=true
Prod6: Id=6, Name="Laptop", Active=true
我想要执行的是获得如下缩小列表:
Prod1: Id=4, Name="Laptop", Active=true
我想要做的是我需要按名称选择所有产品组,并返回所有真实的产品。由于Book有一个假,它不应该返回Book。
我试过这个:
lstProducts = lstProducts
.Where(x =>
lstProducts
.All(c => c.Name == x.Name && c.Active == true))
.GroupBy(c => c.Name).Select(c => c.First())
.ToList();
但它的归零结果。如果我做了一个where clause where Active == true
,它就会获得一个Book产品,因为它的所有Active都应该是真的才能得到它。
答案 0 :(得分:8)
您要找的是首先按照Name
对所有项目进行分组,然后仅过滤那些true
Active
的所有项目,并最后检索每个组的第一项:
var result = lstProducts.GroupBy(item => item.Name)
.Where(group => group.All(item => item.Active)
.Select(group => group.First());
如果您想确保该组的某些排序,请在示例中填写:
var result = lstProducts.GroupBy(item => item.Name)
.Where(group => group.All(item => item.Active)
.Select(group => group.OrderBy(item => item.Id).First());
答案 1 :(得分:4)
先分组,然后过滤:
lstProducts
.GroupBy(c => c.Name)
.Where(g => g.All(c => c.Active))
.Select(g => g.First())
.ToList()
GroupBy
保证组内的项目在分组之前具有相同的顺序。如果您要选择具有最小ID的元素来表示该组,并且您的原始列表未按ID排序,则可以使用Min
代替First
:
lstProducts
.GroupBy(c => c.Name)
.Where(g => g.All(c => c.Active))
.Select(g => g.Min(c => c.Id))
.ToList()