C# 从两个列表c中获取匹配项的最快方法#

C# 从两个列表c中获取匹配项的最快方法#,c#,performance,linq,collections,C#,Performance,Linq,Collections,我有两张单子 清单1 只有两处房产。 无法使用字典,因为可能有重复的键。 房地产1和房地产2的组合是独一无二的 public class List1 { public string Property1 { get; internal set; } public string Property2 { get; internal set; } } public class List2 { public string Property1 { get; internal set;

我有两张单子

清单1 只有两处房产。 无法使用字典,因为可能有重复的键。 房地产1和房地产2的组合是独一无二的

public class List1
{
    public string Property1 { get; internal set; }
   public string Property2 { get; internal set; }
}

public class List2
{
    public string Property1 { get; internal set; }
    public string Property2 { get; internal set; }
    public string Property3 { get; internal set; }
}

List<List1> mylist1 = new List<List1>() {
    new List1() {Property1="664",Property2="Ford" },
    new List1() {Property1="665",Property2="Ford" },
    new List1() {Property1="664",Property2="Toyota" },
};

List<List2> mylist2 = new List<List2>() {
    new List2() {Property1="664",Property2="Ford" ,Property3="USA"},
    new List2() {Property1="665",Property2="Ford" ,Property3="USA"},
    new List2() {Property1="664",Property2="Toyota" ,Property3="USA"},
    new List2() {Property1="666",Property2="Toyota" ,Property3="USA"},
};
这很好用。但是有没有更好/最快的方法来做到这一点


我可以将列表1更改为任何其他类型。但不是列表2。

您正在尝试对LINQ中的数据列表执行
set
操作。有四个LINQ函数调用可用于使当前代码更简洁。这些行动是:

  • 除了
  • 联合
  • 相交
  • 明显的
你要找的是Intersect,它是

返回在两个不同集合中发现不相同的值集

最后,如果您总是要使用这些特定属性来检测相等性和/或唯一性,则需要为List1和/或List2类重写
Equals
。这将取决于谁位于Intersect的左侧(变量之前),谁位于Intersect的右侧(传递到函数中的变量)


如果您不知道如何重写
Equals
函数,请参阅。巧合的是,它还有一个
Intersect
示例。

您正在尝试对LINQ中的数据列表执行
set
操作。有四个LINQ函数调用可用于使当前代码更简洁。这些行动是:

  • 除了
  • 联合
  • 相交
  • 明显的
你要找的是Intersect,它是

返回在两个不同集合中发现不相同的值集

最后,如果您总是要使用这些特定属性来检测相等性和/或唯一性,则需要为List1和/或List2类重写
Equals
。这将取决于谁位于Intersect的左侧(变量之前),谁位于Intersect的右侧(传递到函数中的变量)


如果您不知道如何重写
Equals
函数,请参阅。巧合的是,它还有一个
Intersect
示例。

这两个属性都是字符串,因此您只需创建一个带有键的字典,即那些属性的串联,值为实际项


因此,对于其他列表中的每个项目,只要在字典中查找其属性的串联,如果存在匹配,将两个属性与找到的项进行比较

这两个属性都是字符串,这样您就可以创建一个带有键的字典,键是那些属性的串联,值为实际项


因此,对于另一个列表中的每个项目,您只需在字典中查找其属性的连接,如果存在匹配项,您可以将其与找到的项目进行比较,这是在Linq中进行比较的最简单方法,它相对较快,或者至少比使用
Join
GroupJoin
的方法快,如下所示:

List<List1> matchingCodes = mylist1.GroupJoin(mylist2,

               l1 => new { l1.Property1, l1.Property2 },// Define how the key from List1 looks like
               l2 => new { l2.Property1, l2.Property2 },// Define how the key from List2 looks like

               // Define what we select from the match between list1 and list2
               (l1Item, l2Items) => l1Item).ToList();

在Linq中执行此操作的最简单方法是使用
Join
GroupJoin
,它相对较快,至少比您的方法快,如下所示:

List<List1> matchingCodes = mylist1.GroupJoin(mylist2,

               l1 => new { l1.Property1, l1.Property2 },// Define how the key from List1 looks like
               l2 => new { l2.Property1, l2.Property2 },// Define how the key from List2 looks like

               // Define what we select from the match between list1 and list2
               (l1Item, l2Items) => l1Item).ToList();

您还可以执行加入:

var query= from l in mylist1
           join e in mylist2 on new {Property1=l.Property1,Property2=l.Property2} equals new {Property1=e.Property1,Property2=e.Property2}
           select l;

您还可以执行加入:

var query= from l in mylist1
           join e in mylist2 on new {Property1=l.Property1,Property2=l.Property2} equals new {Property1=e.Property1,Property2=e.Property2}
           select l;


对于OP情况,这需要自定义
IEqualityComparer
实现。基于匿名类型的连接解决方案更简单、更灵活。在看到评论之前,我正在编辑它。现在应该到了。虽然我走的是平等的路线。此外,还被问及是否有“更好”的方法。这是非常固执己见的,因为在代码中阅读比所有的
join
答案更容易。但是对于OP案例,这需要自定义
IEqualityComparer
实现。基于匿名类型的连接解决方案更简单、更灵活。在看到评论之前,我正在编辑它。现在应该到了。虽然我走的是平等的路线。此外,还被问及是否有“更好”的方法。这是非常固执己见的,因为在代码中阅读比所有的
join
答案都要容易。来吧,格式一致的契约Lnq很少是最优秀的选项格式一致的契约Lnq很少是最优秀的选项我想你可以省略“名称”让它更具可读性
new{Property1=l.Property1,Property2=l.Property2}
=>
new{l.Property1,l.Property2}
谢谢@CSharpie,我知道这一点,但是如果这两个类之间的属性名称不同,那么有必要这样做。我假设这些不是真名,但如果它们的名称匹配,是的,匿名类型中的属性名称可以省略。你是对的,这使你的答案更防水。我用我的方法和上面建议的方法做了一个快速基准测试。我的方法是54毫秒。建议-116毫秒我想你可以省略“名字”让它更具可读性
new{Property1=l.Property1,Property2=l.Property2}
=>
new{l.Property1,l.Property2}
谢谢@CSharpie,我知道这一点,但是如果这两个类之间的属性名称不同,那么有必要这样做。我假设这些不是真名,但如果它们的名称匹配,是的,匿名类型中的属性名称可以省略。你是对的,这使你的答案更防水。我用我的方法和上面建议的方法做了一个快速基准测试。我的方法是54毫秒。建议-116 msI用我的方法和上面建议的方法做了一个快速基准测试。我的方法是54毫秒。建议-112ms@Gokul这实际上取决于这些列表中的项目数量。如果这个数字很小,那么连接在工作之前创建这些哈希表的开销可能会更大。我的回答还假设您的列表中包含的项目多于其他项目