Gokul
Gokul

Reputation: 1371

Fastest way to get matching items from two list c#

I have two lists

List1 Only two property. Cant use Dictionary since there might be duplicate keys. The combination of Property1 and Property2 is unique.

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

I need to get the matching items in mylist1 and mylist2. The match should happen only on Property1 and Property2. Property3 in the mylist2 can be ignored during comparison.

Currently I use

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

which works perfectly fine. But is there a better way/ fastest way to do this?

I can change List1 to any other Type. but not List2.

Upvotes: 4

Views: 4511

Answers (4)

Martin Hollstein
Martin Hollstein

Reputation: 528

You are trying to do set operations on your data lists in LINQ. There are four LINQ function calls that you can use to make the current code cleaner as well as succinct. These operations are:

  • Except
  • Union
  • Intersect
  • Distinct

The one you are looking for is Intersect which is

Returns the set of values found t be identical in two separate collections Source

Finally, if you are always going to use those specific properties to detect equality and/or uniqueness you will need to override Equals for List1 and/or List2 classes. This would depend who is considered on the left hand of the Intersect (the variable before the .) and who is on the right hand of the Intersect (the variable passed into the function).

Here is a SO answer to how to override the Equals function if you do not know how to do so. Coincidentally, it also has an Intersect example.

Upvotes: 3

CSharpie
CSharpie

Reputation: 9467

The easiest way to do it in Linq which is relatively fast, or atleast faster than your approach is using Join or GroupJoin like so:

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

Simplified, this creates two dictionaries which are then joined together.

GroupJoin works better here as it gives you the item from List1 and all matching from list2.

A regular Join would return the same item from List1 per match from List2.

See also Enumerable.GroupJoin (C# Reference)

Note this is the equivalent to @octavioccl's answer. Also this example assumes, the names of the properties from both classes are equal. If they arent you have to modifiy they keyselectors abit like so:

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

Upvotes: 3

ocuenca
ocuenca

Reputation: 39326

You could also do a join:

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;

Upvotes: 3

Stefan Georgiev
Stefan Georgiev

Reputation: 170

Both properties are strings so that you can just create a dictionary with a key the concatenation of those properties with a Value of the actual item.

So for each item in the other list you can just look up in the dictionary for the concatenation of their property, if there is a match, you compare with the item found

Upvotes: 0

Related Questions