【问题标题】:Joining two lists in LINQ在 LINQ 中加入两个列表
【发布时间】:2016-02-21 07:46:06
【问题描述】:

假设我有两个位置列表。 First 包含所有可用位置:

List<Location> locations = new List<Location> {
   new Location { id = 1, address = "1 Main St.", selected = false },
   ...
}

另一个是 my 个位置的列表或数组:

List<int> myLocations = new List<int> { 1, 5, 8 };

(ID 是不可预测的,但我的位置保证是所有位置的子集)。

我想外连接两个列表并获得selected = true 位置where locations.id eq myLocations 的结果。

如果我使用 Join() 或 Zip(),那么我会得到 inner join,换句话说,我会丢失 myLocations 中不存在的元素,如果我使用以下 -

var result = from loc in locations
    join my in myLocations
       on loc.id equals my into myloc
    from m in myloc.DefaultIfEmpty()
       select new Location {
          id = loc.id, address = loc.address, selected = true
       };

然后所有位置被标记为选中;更不用说它看起来过于复杂了。 有没有办法在不循环列表元素的情况下做我想做的事?

【问题讨论】:

    标签: c# linq join


    【解决方案1】:

    因为您需要为内存中的每个location 设置selected 属性,所以您可以使用ForEach 扩展方法,如下面的代码:

    locations.ForEach(location => location.selected = myLocations
        .Any(id => id == location.id)
    );
    

    使用此代码,您不会像使用投影 (select new Location) 那样在内存中创建 Location 的新实例。将同一实例放入您的locations 中。

    【讨论】:

    • 你说得对,谢谢!然而,现实是我可以首先应用@tchlidze 答案来构建列表。也就是说,我不会有一个包含所有“选定”成员的列表 false 来首先应用 ForEach...
    【解决方案2】:

    根据你所说的

    我的位置保证是所有位置的子集

    您可以实现LEFT JOIN 而不是OUTER JOIN。

    尝试关注

      locations.Select(l => new Location
      {
        id = l.id,
        adress = l.adress,
        selected = myLocations.Any(ml => ml == l.id)
      })
    

    【讨论】:

    • 所有答案都很棒,可以实施。事实上,我很尴尬一开始就错过了 Any() 选项。我最喜欢这个,因为我可以在“上游”实现它——也就是说,当我从数据库中获取数据时。 Kamarjoba, Genatsvali :)
    • @Felix 很高兴帮助 Felix。很高兴你知道格鲁吉亚语^^。 Gmertma gagimarjos :)
    【解决方案3】:

    你很亲密。

    在最后一个查询中,您实际上实现了所谓的左外连接,但更适合这种情况的是group join。

    由于LINQ中的left outer join实际上是通过group join实现的,所以只需要去掉那一行

    from m in myloc.DefaultIfEmpty()
    

    并像这样使用selected = myloc.Any()

    var result = from loc in locations
        join my in myLocations
           on loc.id equals my into myloc
        select new Location {
              id = loc.id, address = loc.address, selected = myloc.Any()
        };
    

    【讨论】:

      【解决方案4】:

      CodeNotFound 的回答是如果可以修改原来的 Location 对象是有效的。

      如果您需要一些纯粹作为查询而没有副作用的东西(这通常更符合 Linq 的精神),那么以下内容将起作用。 这类似于 tchelidze 的回答,但避免为所有不匹配的对象创建新实例:

      locations.Select(l => myLocations.Any(i => i == l.id) ? 
          new Location {id = l.id, address = l.address, selected = true } : l);
      

      或使用查询语法:

      from location in locations
      select myLocations.Any(i => i == location.id) 
          ? new Location { 
               id = location.id, 
               address = location.address, 
               selected = true }
          : location;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-19
        • 2021-07-23
        • 1970-01-01
        • 2016-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多