在LINQ

时间:2016-02-21 07:46:06

标签: c# linq join

假设我有两个位置列表。首先是所有可用的位置:

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 myLocation的结果。

如果我使用Join()或Zip(),那么我得到内连接,换句话说,我丢失了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
       };

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

4 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

根据您的陈述

  

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

您可以实施LEFT JOIN而不是OUTER JOIN

尝试以下

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

答案 2 :(得分:1)

你是如此亲密。

在上一个查询中,您实际实现了所谓的左外连接,但更适合此方案的是group join

由于LINQ中的左外连接实际上是通过 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()
    };

答案 3 :(得分:0)

CodeNotFound的答案是有效的,如果可以修改原始位置对象。

如果您需要的东西纯粹作为没有副作用的查询(通常更符合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;