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

时间:2017-02-17 19:15:06

标签: c# performance linq collections

我有两个列表

的List1 只有两个属性。 不能使用Dictionary,因为可能有重复的键。 Property1和Property2的组合是唯一的。

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"},
};

我需要获取mylist1和mylist2中的匹配项。匹配应仅在Property1和Property2上进行。在比较期间,可以忽略mylist2中的Property3。

目前我使用

var matchingCodes = mylist1.Where(l1 => mylist2.Any(l2 => (l2.Property1 == l1.Property1 && l2.Property2==l1.Property2))).ToList();

完美无缺。但有没有更好的方法/最快的方法呢?

我可以将List1更改为任何其他类型。但不是List2。

4 个答案:

答案 0 :(得分:3)

在Linq中执行此操作的最简单方法是使用JoinGroupJoin这样的方法相对较快,或者至少快于您的方法:

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();

简化,这会创建两个字典,然后将它们连接在一起。

GroupJoin在这里工作得更好,因为它为您提供了List1中的项目和来自list2的所有匹配项。

常规Join将从List2返回每个匹配的List1中相同的项目。

另见Enumerable.GroupJoin (C# Reference)

注意这相当于@octavioccl's answer。 此示例还假设,两个类的属性名称相同。如果他们不是你必须修改他们的键选择器如此:

l1 => new { A=l1.Foo, B=l1.Bar},
l2 => new { A=l2.Herp, B=l2.Derp},

答案 1 :(得分:3)

你也可以加入:

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;

答案 2 :(得分:2)

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

  • 联盟
  • 相交
  • 鲜明

您正在寻找的是Intersect,它是

  

返回在两个单独的集合中找到的相同值集   Source

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

Here is a SO answer了解如何覆盖Equals函数,如果您不知道如何执行此操作。巧合的是,它也有一个Intersect例子。

答案 3 :(得分:0)

这两个属性都是字符串,因此您只需创建一个字典,其中包含这些属性的串联,其值为实际项

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