C# linq 是否支持 "anti join" 语义?
Does C# linq support "anti join" semantics?
我用谷歌搜索了一会儿,没有找到直接的反连接语义示例。如何在 C# LINQ 中执行此操作?
anti-join 基本上是一组不包含在另一组数据中的数据,可以在 Linq
中用 IEnumerable.Except
表示像这样:
double[] numbers1 = { 2.0, 2.0, 2.1, 2.2, 2.3, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.2 };
IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
foreach (double number in onlyInFirstSet)
Console.WriteLine(number);
这当然需要为自定义 类.
定义一个 IEqualityComparer
另一种使用 where
的语法是:
var antiJoin = numbers1.Where(number => !numbers2.Contains(number));
在 Microsoft 文档中阅读有关 Enumerable.Except Method 的更多信息。
编辑:
至于“db driven linq”,这里有一个使用 Except
:
适用于 Entity Framework
的示例
var filteredProducts = db.Products.ToList()
.Except(db.Orders.Where(o => o.OrderId = 123)
.Select(o => o.Product).ToList())
.ToList();
至于 where
备选方案:
var filterProducts = db.Orders.Where(o => o.OrderId = 123)
.Select(o => o.Product).ToList();
var antiJoinProducts = db.Products.Where(p => !filterProducts.Contains(p));
我认为没有直接的方法可以实现这一点,但使用一些扩展方法很容易。
设置:
public class Class1
{
public int Id;
public string Info;
}
public class Class2
{
public int Id;
public string Data;
}
用法:
List<Class1> l1 = new List<Class1>() { new Class1() { Id = 1, Info = "abc" }, new Class1() { Id = 2, Info = "123" } };
List<Class2> l2 = new List<Class2>() { new Class2() { Id = 2, Data = "dsfg" }, new Class2() { Id = 3, Data = "asdfsaf" } };
l1 = l1.Where(c1 => ! l2.Select(c2 => c2.Id).Contains(c1.Id)).ToList();
此外,如果您有与 entites/types 相同的列表,您可以使用 Except
方法(您需要定义自己的比较器)。
假设这与您之前的问题有关 -
如果您想在查询中包含找不到部门(本质上是 left outer join
)的员工,您可以这样做:
var result = from e in employees
join d in departments on e.DeptId equals d.DeptId into gj
from subdept in gj.DefaultIfEmpty()
select new { e.EmpName, subdept?.DeptName };
如果您只想检索无法匹配部门的员工(我猜那是您的 anti join
),那么您只需添加一个 subdept is null
条件,如下所示:
var result = from e in employees
join d in departments on e.DeptId equals d.DeptId into gj
from subdept in gj.DefaultIfEmpty()
where subdept is null
select new { e.EmpName, subdept?.DeptName };
有关 C# Linq 中 left outer join
的更多信息,您可以查看 this。
我用谷歌搜索了一会儿,没有找到直接的反连接语义示例。如何在 C# LINQ 中执行此操作?
anti-join 基本上是一组不包含在另一组数据中的数据,可以在 Linq
中用 IEnumerable.Except
表示像这样:
double[] numbers1 = { 2.0, 2.0, 2.1, 2.2, 2.3, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.2 };
IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
foreach (double number in onlyInFirstSet)
Console.WriteLine(number);
这当然需要为自定义 类.
定义一个IEqualityComparer
另一种使用 where
的语法是:
var antiJoin = numbers1.Where(number => !numbers2.Contains(number));
在 Microsoft 文档中阅读有关 Enumerable.Except Method 的更多信息。
编辑:
至于“db driven linq”,这里有一个使用 Except
:
Entity Framework
的示例
var filteredProducts = db.Products.ToList()
.Except(db.Orders.Where(o => o.OrderId = 123)
.Select(o => o.Product).ToList())
.ToList();
至于 where
备选方案:
var filterProducts = db.Orders.Where(o => o.OrderId = 123)
.Select(o => o.Product).ToList();
var antiJoinProducts = db.Products.Where(p => !filterProducts.Contains(p));
我认为没有直接的方法可以实现这一点,但使用一些扩展方法很容易。
设置:
public class Class1
{
public int Id;
public string Info;
}
public class Class2
{
public int Id;
public string Data;
}
用法:
List<Class1> l1 = new List<Class1>() { new Class1() { Id = 1, Info = "abc" }, new Class1() { Id = 2, Info = "123" } };
List<Class2> l2 = new List<Class2>() { new Class2() { Id = 2, Data = "dsfg" }, new Class2() { Id = 3, Data = "asdfsaf" } };
l1 = l1.Where(c1 => ! l2.Select(c2 => c2.Id).Contains(c1.Id)).ToList();
此外,如果您有与 entites/types 相同的列表,您可以使用 Except
方法(您需要定义自己的比较器)。
假设这与您之前的问题有关 -
如果您想在查询中包含找不到部门(本质上是 left outer join
)的员工,您可以这样做:
var result = from e in employees
join d in departments on e.DeptId equals d.DeptId into gj
from subdept in gj.DefaultIfEmpty()
select new { e.EmpName, subdept?.DeptName };
如果您只想检索无法匹配部门的员工(我猜那是您的 anti join
),那么您只需添加一个 subdept is null
条件,如下所示:
var result = from e in employees
join d in departments on e.DeptId equals d.DeptId into gj
from subdept in gj.DefaultIfEmpty()
where subdept is null
select new { e.EmpName, subdept?.DeptName };
有关 C# Linq 中 left outer join
的更多信息,您可以查看 this。