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%.