One of the recent requirements I came across recently needed what looks like a Join on a ‘Like%’. Let me cite an example to demonstrate the requirement.
Consider the Collections below.
Master Collection
ID | Name |
---|---|
1 | Jia Anu |
2 | Sreena Anu |
3 | Anu Viswan |
Child Collection
ID | First Name | Age |
---|---|---|
1 | Jia | 2 |
3 | Sreena | 34 |
5 | Anu | 35 |
I would like to Join on Master.Name and Child.FirstName where Child.FirstName StartsWith Master.Name. The expected output is as follows.
Name | FirstName | Age |
---|---|---|
Jia Anu | Jia | 2 |
Sreena Anu | Sreena | 34 |
Anu Viswan | Anu | 35 |
Let’s begin by defining the input collections.
var master = new List<Master> { new Master{Id=1,Name="Jia Anu"}, new Master{Id=2,Name="Sreena Anu"}, new Master{Id=3,Name="Anu Viswan"} }; var child = new List<Child> { new Child{Id=1,FirstName="Jia",Age=2}, new Child{Id=2,FirstName="Sreena",Age=34}, new Child{Id=3,FirstName="Anu",Age=35} };
Where Master and Child is defined as
public class Master { public int Id {get;set;} public string Name {get;set;} } public class Child { public int Id{get;set;} public string FirstName {get;set;} public int Age {get;set;} }
The default Join uses Equality as Comparer, and is not useful for us in this scenario. The solution lies in a little known overload of Group, which allows to provide our own customer Comparer. Let’s define our Custom Comparer.
class StartsWithEqualityComparer: IEqualityComparer<string> { public bool Equals(string right, string left) { return left.StartsWith(right); } public int GetHashCode(string obj) { return 0; } }
Now, we can use our StartsWithEqualityComparer.
var result = master.Join(child, m=>m.Name, c=>c.FirstName, (m,c)=> new { Name = m.Name,FirstName = c.FirstName,Age = c.Age } },new StartsWithEqualityComparer());
That’s it, we have our GroupBy with Like%.