从列表中删除不在* all *位置的项目

时间:2014-06-10 13:56:53

标签: c# linq generics

我的对象看起来像:

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...
    );

因为这只检查了我必须为所有区域重复的一个区域 - 不是非常优雅的代码。任何想法或帮助表示赞赏!

3 个答案:

答案 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);

我提供以下反馈: -

  1. 我为了清晰而不是简洁而进行优化。许多开发人员发现密集的LINQ难以阅读,明确的意图陈述(itemsNotAtAllLocations)可以节省大量时间。

  2. 您的版本可以节省创建(可能很小的)数据结构,但代价是更频繁地迭代(可能是大的)数据结构。 Prima facie 对我来说听起来更像是工作,而不是更少。

  3. 我非常怀疑性能影响无论如何都会显着。

  4. 如果绩效对您很重要,您应该设定一个以利益相关者为中心的基准,并在现实条件下进行衡量。

  5. 如果表现对您非常重要,我希望您采取不同的方法可以做得更好,例如你可以在数据库层进行查询,还是可以在第一时间使用更合适的数据结构(即一个代表分组的数据结构)?

答案 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且关键是好的。