I need to do an intersect between strings but comparing substrings:
public class MiNumeroEqualityComparer : IEqualityComparer<string> {
public bool Equals(string x, string y) => x.Contains(y);
public int GetHashCode(string obj) => obj.GetHashCode();
}
List<string> lst = new List<string> { "abcXdef", "abcXdef", "abcede", "aYcde" };
List<string> num = new List<string> { "X", "Y", "Z" };
var fin = lst.Intersect(num, new MiNumeroEqualityComparer());
I expect in fin: "abcXdef", "abcXdef", "aYcde"
But it's empty, why?
First I've tried substring with case insensitive with: (without success too)
public bool Equals(string x, string y) => x.IndexOf(y, StringComparison.InvariantCultureIgnoreCase) >= 0;
But empty too.
You're doing an intersection between two lists, which will give you the common items between them. Since neither list contains an identical item, you are getting no results.
If you want to get all the items from lst
that contain an item from num
, then you can do something like the code below, which uses the string.Contains
method to filter the items from lst:
var fin = lst.Where(item => num.Any(item.Contains));
Result:
{ "abcXdef", "abcXdef", "aYcde" }
Alternatively, if you do want to do a case-insensitive query, you can use the IndexOf
method instead:
var fin = lst.Where(item => num.Any(n =>
item.IndexOf(n, StringComparison.OrdinalIgnoreCase) >= 0));
If that's hard to understand (sometimes Linq is), the first code snippet above is a shorthand way of writing the following:
var fin = new List<string>();
foreach (var item in lst)
{
foreach (var n in num)
{
if (item.Contains(n))
{
fin.Add(item);
break;
}
}
}