我的对象看起来像:
public class ListItem {
public int ItemId { get; set; }
public int LocationId { get; set; }
// ... other properties ...
}
我有从数据库加载的这些项目(List<ListItem>
)的列表。这些项目ID 和位置ID是唯一的。我碰巧知道总共只有10个位置(LocationId为1 - 10)。
我是否可以编写LINQ声明来删除不会出现在所有 10个位置的内容?
我现在拥有的是:
myList.RemoveAll(x =>
// this line would need repeated 10 times to work!
!myList.Any(y => y.ItemId == x.ItemId && y.LocationId == 1) &&
!myList.Any(y => y.ItemId == x.ItemId && y.LocationId == 2)
// etc...
);
因为这只检查了我必须为所有区域重复的一个区域 - 不是非常优雅的代码。任何想法或帮助表示赞赏!
答案 0 :(得分:5)
您可以使用GroupBy按ItemId
对元素进行分组,然后删除分组中不包含10个项目的所有元素: -
var itemsNotAtAllLocations = myList.GroupBy(x => x.ItemId)
.Where(g => g.Count() != 10)
.Select(g => g.Key);
myList.RemoveAll(x => itemsNotAtAllLocations.Contains(x.ItemId));
或者如果您更喜欢查询语法: -
var itemsNotAtAllLocations = from item in mylist
group item by item.ItemId into g
where g.Count() != 10
select g.Key;
评论中有建议改为: -
myList.RemoveAll(x => myList.Count(y => y.ItemId == x.ItemId) != 10);
我提供以下反馈: -
我为了清晰而不是简洁而进行优化。许多开发人员发现密集的LINQ难以阅读,明确的意图陈述(itemsNotAtAllLocations
)可以节省大量时间。
您的版本可以节省创建(可能很小的)数据结构,但代价是更频繁地迭代(可能是大的)数据结构。 Prima facie 对我来说听起来更像是工作,而不是更少。
我非常怀疑性能影响无论如何都会显着。
如果绩效对您很重要,您应该设定一个以利益相关者为中心的基准,并在现实条件下进行衡量。
如果表现对您非常重要,我希望您采取不同的方法可以做得更好,例如你可以在数据库层进行查询,还是可以在第一时间使用更合适的数据结构(即一个代表分组的数据结构)?
答案 1 :(得分:0)
像这样使用IList.Contains()
:
var locationIds = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
myList.RemoveAll(x => !myList.Any(y => y.ItemId == x.ItemId && locationIds.Contains(y.LocationId));
答案 2 :(得分:0)
var test1 = from g in myList
group g by g.ItemId into grp
select new { key = grp.Key, cnt = grp.Count() };
只需检查计数是否为10且关键是好的。