这两种使用 LINQ 执行 Left Outer Join 的方法有什么区别,因为我都使用了两个买家和供应商列表,并按公共(public)区域加入它们以查找同一区域的供应商和买家。
class Supplier
{
public string Name { get; set; }
public string District { get; set; }
}
class Buyer
{
public string Name { get; set; }
public string District { get; set; }
}
List<Buyer> buyers = new List<Buyer>()
{
new Buyer() { Name = "Johny", District = "Fantasy District" },
new Buyer() { Name = "Peter", District = "Scientists District" },
new Buyer() { Name = "Paul", District = "Fantasy District" },
new Buyer() { Name = "Maria", District = "Scientists District" },
new Buyer() { Name = "Joshua", District = "EarthIsFlat District" },
new Buyer() { Name = "Sylvia", District = "Developers District" },
new Buyer() { Name = "Rebecca", District = "Scientists District" },
new Buyer() { Name = "Jaime", District = "Developers District" },
new Buyer() { Name = "Pierce", District = "Fantasy District" }
};
List<Supplier> suppliers = new List<Supplier>()
{
new Supplier() { Name = "Harrison", District = "Fantasy District" },
new Supplier() { Name = "Charles", District = "Developers District" },
new Supplier() { Name = "Hailee", District = "Scientists District" },
new Supplier() { Name = "Taylor", District = "EarthIsFlat District" }
};
首先:
var suppliersAndBuyers = from s in suppliers
orderby s.District
join b in buyers on s.District equals b.District into buyersGroup
select buyersGroup.DefaultIfEmpty(
new Buyer()
{
Name = string.Empty,
District = s.District
});
foreach (var item in suppliersAndBuyers)
{
foreach (var buyer in item)
{
Console.WriteLine($"{buyer.District} {buyer.Name}");
}
}
第二种方法:
var suppliersAndBuyers = from s in suppliers
orderby s.District
join b in buyers on s.District equals b.District into buyersGroup
from bG in buyersGroup.DefaultIfEmpty()
select new
{
Name = bG.Name == null ? string.Empty : bG.Name,
s.District,
};
foreach (var item in suppliersAndBuyers)
{
Console.WriteLine($"{item.District} {item.Name}");
}
两者都产生完全相同的输出,唯一的区别是我们输出结果的方式吗?我应该使用哪一个?
编辑:第一种方法返回 IEnumerable<IEnumerable<Buyer>>
第二个返回 IEnumerable<AnonymousType>
,两者之间唯一有意义的区别在于它们返回的类型,这是两种方法之间唯一的决定因素,无论我想要一个类型还是匿名类型?
最佳答案
好的。据我所见:(A)
var suppliersAndBuyers = from s in suppliers
orderby s.District
枚举供应商列表。这很明显。现在,将其加入买家名单:
var suppliersAndBuyers = from s in suppliers
orderby s.District
join b in buyers on s.District equals b.District
这会创建匹配项(有些对象我不知道其类型,因为我面前没有正常的 Visual Studio 实例)。但例如,它就像 Harrison:Jonnie, Hailee:Peter, ...
.现在我们可以基于这些匹配项(由变量 b
和 s
表示)创建对象的 IEnumerable,如下所示:
var suppliersAndBuyers = from s in suppliers
orderby s.District
join b in buyers on s.District equals b.District
select new {
Supplier = s, Buyer = b
}
这将创建一个匿名类型的 IEnumerable,每个对象代表一对供应商和买方。
var suppliersAndBuyers = from s in suppliers
orderby s.District
join b in buyers on s.District equals b.District into buyersGroup
但是您决定做的是左连接,如标题中所写。它的作用是获取在片段 (A) 中创建的列表中的每个元素,并匹配一个 IEnumerable
。买家列表中的所有匹配对象。这会产生可枚举的匹配项。例如,对于 Harrison,suppliers
中的第一个条目列表,你会得到一个 IEnumerable
包含 Johnny、Paul 和 Pierce。 suppliers
中的其他元素相同列表,按他们的 District
排序.
这就是为什么你以 IEnumerable<IEnumerable<Buyer>>
结尾的原因.因为对于每个供应商(第一个 IEnumerable 维度),您都有一个 Buyer
的“列表” (二次元+类型解释)
然后合并空条目在我看来已经过时了,因为你不应该有 null
s,但只是空的 IEnumerable
s,然后在遍历它们时,您将不会碰到任何元素。 (虽然我不确定最后一段,因为我从来没有编译过代码所以我不知道)
现在至于合并部分,第一个示例创建了一个新的 Buyer
每个条目的对象,然后取 DefaultIsEmpty
.对于第二个示例,它首先创建第一维和第二维 FULL IEnumerables,然后在再次迭代时合并空值。正如我在评论中提到的,这是一个不需要的循环。
关于c# - Left Outer Join,这两种方法有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49017141/