代码之家  ›  专栏  ›  技术社区  ›  lost9123193

使用。Where子句和筛选数组的条件

  •  0
  • lost9123193  · 技术社区  · 6 年前

    我有2个 IEnumerable 具有名为 GetId() 返回 integer

    IEnumerable oldBoats
    IEnumerable updatedBoats
    

    我想比较两个列表。如果 updatedBoats.getId() 返回唯一的Id,与 oldBoats ,我想将其添加到列表中。

    所以我这样做了:

    IEnumerable<Boat> newBoats = updatedBoats
        .Where(c => oldBoats
        .Any(d => d.GetId() != c.GetId())
        .ToList()
    

    的当前ID 旧船 newBoats [1, 2, 3, 4, 5] 。我想测试基本情况,但此操作未通过。这个 新船 总是在应该返回的时候返回所有ID的列表 none .我是在点菜吗 c d 错误的

    2 回复  |  直到 6 年前
        1
  •  6
  •   zeroef    6 年前

    这个怎么样?

    var newBoats = updatedBoats.Where(u => !oldBoats.Any(o => o.GetId() == u.GetId()));
    
        2
  •  4
  •   Chris Shain    6 年前

    此代码的作用

    IEnumerable<Boat> newBoats = updatedBoats.Where(c=> oldBoats.Any(d =>d.GetId() != c.GetId()).ToList()
    

    大致翻译为:“给我所有更新的船,其ID与至少一个旧船ID不匹配”。那不是你想要的。您想要的逻辑是“给我所有ID与旧船ID不匹配的更新船”,这是由@zeroef正确指定的:

    var newBoats = updatedBoats.Where(u => !oldBoats.Any(o => o.GetId() == u.GetId()));  
    // This is O(o * n) for # of old boats * # of updates that are new boats, and something like O((o/2)*n) for # of old boats * number of updated old boats
    

    尽管如此,请注意我的评论。使用 HashSet<T> :

    // This is O(n) for # of updated boats
    var newBoatIds = new HashSet<Int32>(updatedBoats.Select(b => b.GetId())); 
    // This is O(n) for # of old boats
    newBoatIds.ExceptWith(oldBoats.Select(b => b.GetId()));
    

    这显著减少了嵌套迭代的数量,如果您有很多船(尤其是更新中有很多新船),您将看到不同。

    HashSet方法适用于ID,但如果使用ID在Boat类上实现Equals()和GetHashcode()进行比较,则也可以使其适用于实体本身。