Linq相交或连接返回一个集合中与另一个集合具有匹配属性的项

本文关键字:集合 另一个 属性 一个 连接 返回 Linq | 更新日期: 2023-09-27 18:09:39

我有以下场景:两个不同的Types列表恰好包含3个匹配的属性(实际上,名称不相同,因为它们来自不同的系统/数据库表,但它们的内容匹配)。

在我的例子中,我将属性命名为相同只是为了使它更容易!

我想获得Prefix+Number+Suffix的帐户列表,在查找中有一个匹配的项目(注意:查找可以多次包含相同的值-对象中的其余属性不同)

这是我目前正在使用的代码,但感觉很笨拙。有没有一种更干净、更好的方法来达到同样的结果?我尝试了"Contains()",但不确定如何限制所有三个属性。

    var accounts = new List<Account>{
        new Account{Prefix="001", Number="10101", Suffix="666"},
        new Account{Prefix="001", Number="10202", Suffix="777"},
        new Account{Prefix="001", Number="10303", Suffix="777"},
        new Account{Prefix="002", Number="20101", Suffix="666"},
        new Account{Prefix="002", Number="20101", Suffix="777"}
    };
    var lookup = new List<Lookup>{
        new Lookup{Prefix="001", Number="10101", Suffix="666"},
        new Lookup{Prefix="001", Number="10101", Suffix="666"},
        new Lookup{Prefix="002", Number="20101", Suffix="666"},
        new Lookup{Prefix="001", Number="10101", Suffix="666"},
    };
    var match = ((from a in accounts
                  select a)
                 .Intersect(from l in lookup
                            from a in accounts
                            where l.Prefix == a.Prefix &&
                            l.Number == a.Number &&
                            l.Suffix == a.Suffix
                            select a)
                            ).Select(a => string.Format("{0}{1}{2}", a.Prefix, a.Number, a.Suffix));

Linq相交或连接返回一个集合中与另一个集合具有匹配属性的项

您可以使用以下代码来获得匹配:

var match = (from a in accounts
             select new { P = a.Prefix, N = a.Number, S = a.Suffix })
  .Intersect(from l in lookup
             select new { P = l.Prefix, N = l.Number, S = l.Suffix })
  .Select(t => string.Format("{0}{1}{2}", t.P, t.N, t.S));;

您在这里使用匿名类型上自动生成的相等操作符

为什么不直接:

        match = (from l in lookup
                 from a in accounts
                 where l.Prefix == a.Prefix &&
                 l.Number == a.Number &&
                 l.Suffix == a.Suffix
                 select string.Format("{0}|{1}|{2}", l.Prefix, l.Number, l.Suffix))
                 .Distinct();

试试这个:

from a in accounts
join l in lookup on
new
{
    a.Prefix, a.Number, a. Suffix
}
equals
new
{
    l.Prefix, l.Number, l. Suffix
}
into gls
select a

在这种情况下,我不会直接使用表,而是使用数据库视图。创建一个视图,为您执行联合并返回一个规范化的数据结构,如下所示:

CREATE VIEW ExampleView
AS
SELECT
    Prefix = a.Prefix,
    Number = a.Number,
    Suffix = a.Suffix
FROM
    FirstTable AS a
UNION ALL
SELECT
    Prefix = l.Prefix,
    Number = l.NumberWithDifferentName,
    Suffix = l.WeirdlyNamedSuffix
FROM
    SecondTable AS l

然后你可以在这个视图上运行一个简单的选择,而不是在你的应用程序中执行复杂的数据库逻辑,无论如何它都不属于:

SELECT Prefix, Number, Suffix FROM ExampleView; /* or obviously the LINQ equivalent */

这里有一个关于这个问题的文章链接(为什么要使用视图):http://www.tdan.com/view-articles/5109。下面的部分解释了为什么最好的做法是让数据库做它最擅长的事情,而不是应用程序:

开发人员发现必须使用规范化的数据结构既尴尬又耗时,因为它涉及到编写复杂的SQL查询来连接来自多个表的数据。[…[/em>

将非规范化的数据结构"重构"为规范化的数据结构总是非常困难和费力的,有时甚至是不可能的(因为非关键字段中的数据必须"重构"为关键字段,而这些字段中的数据可能有缺失或不正确的值)。

你为什么不试试把它们连起来呢

from a in accounts
join l in lookup 
on
            new { a.Prefix, a.Number, a. Suffix}  
            equals
             new { l.Prefix, l.Number,l. Suffix}  
            select a;