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

dre*_*w_w 2 c# linq generics

我的对象看起来像:

public class ListItem {
    public int ItemId { get; set; }
    public int LocationId { get; set; }
    // ... other properties ...
}
Run Code Online (Sandbox Code Playgroud)

我有一个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...
    );
Run Code Online (Sandbox Code Playgroud)

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

Iai*_*way 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));
Run Code Online (Sandbox Code Playgroud)

或者如果您更喜欢查询语法: -

var itemsNotAtAllLocations = from item in mylist
                             group item by item.ItemId into g
                             where g.Count() != 10
                             select g.Key;
Run Code Online (Sandbox Code Playgroud)

评论中有建议改为: -

myList.RemoveAll(x => myList.Count(y => y.ItemId == x.ItemId) != 10);
Run Code Online (Sandbox Code Playgroud)

我会就此提供以下反馈: -

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

  2. 您的版本可以节省创建(可能很小的)数据结构,但代价是更频繁地迭代(可能是大的)数据结构.初学者看起来对我来说更有用,而不是更少.

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

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

  5. 如果性能对您非常重要,我希望您可以通过采用不同的方法做得更好,例如,您可以在数据库层进行查询,还是可以使用更合适的数据结构(即代表分组的数据结构)首先?