Intersect 上的子字符串比较器
Substring comparer on Intersect
我需要在字符串之间进行交集,但比较子字符串:
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());
我希望在 fin 中:"abcXdef"、"abcXdef"、"aYcde"
但是里面是空的,为什么?
首先,我尝试了不区分大小写的子字符串:(也没有成功)
public bool Equals(string x, string y) => x.IndexOf(y, StringComparison.InvariantCultureIgnoreCase) >= 0;
但也是空的。
Intersect 从 2 个集合中获取公共元素。这里的 Intersect 方法很优雅。它可以用于多种类型的元素。
您的结果为空,因为它不是列表中的常用值。
List<string> lst = new List<string> { "abcXdef", "abcXdef", "abcede", "aYcde" };
List<string> num = new List<string> { "X", "Y", "abcXdef", "Z", "aYcde" };
var fin = lst.Intersect(num);
fin >> abcXdef,aYcde
您正在对两个列表进行交集,这将为您提供它们之间的共同项目。由于两个列表都不包含相同的项目,因此您得不到任何结果。
如果你想从 lst
中获取所有包含来自 num
的项目的项目,那么你可以执行类似下面的代码,它使用 string.Contains
方法来从 lst 过滤项目:
var fin = lst.Where(item => num.Any(item.Contains));
结果:
{ "abcXdef", "abcXdef", "aYcde" }
或者,如果您确实想执行不区分大小写的查询,您可以改用 IndexOf
方法:
var fin = lst.Where(item => num.Any(n =>
item.IndexOf(n, StringComparison.OrdinalIgnoreCase) >= 0));
如果这很难理解(有时 Linq 是),上面的第一个代码片段是 shorthand 编写以下内容的方式:
var fin = new List<string>();
foreach (var item in lst)
{
foreach (var n in num)
{
if (item.Contains(n))
{
fin.Add(item);
break;
}
}
}
当然,Rufus 已经在提供的答案中解决了您的问题。但是让我解释一下为什么您的方法不起作用。
它产生空结果的原因是因为 Equals(string x, string y)
永远不会被调用。它可以从 GetHashCode
方法中推断出不等式。如果哈希值相同,那么它将调用 Equals
。换句话说,你在 Equals
中的逻辑将永远不会被执行。
这是一些代码,您可以看到发生了什么。
class Program
{
static void Main(string[] args)
{
// See I added an item at the end here to show when Equals is called
List<string> lst = new List<string> { "abcXdef", "abcXdef", "abcede", "aYcde", "X" };
List<string> num = new List<string> { "X", "Y", "Z" };
var fin = lst.Intersect(num, new MiNumeroEqualityComparer()).ToList();
Console.ReadLine();
}
}
public class MiNumeroEqualityComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
Console.WriteLine("Equals called for {0} and {1}.", x, y);
return x.Contains(y);
}
public int GetHashCode(string obj)
{
Console.WriteLine("GetHashCode alled for {0}.", obj);
return obj.GetHashCode();
}
}
如果您 运行 上面的代码,它只会为产生相同散列的项目调用 Equals
;所以仅适用于 "X"。
查看 this fiddle 中的输出。
我需要在字符串之间进行交集,但比较子字符串:
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());
我希望在 fin 中:"abcXdef"、"abcXdef"、"aYcde"
但是里面是空的,为什么?
首先,我尝试了不区分大小写的子字符串:(也没有成功)
public bool Equals(string x, string y) => x.IndexOf(y, StringComparison.InvariantCultureIgnoreCase) >= 0;
但也是空的。
Intersect 从 2 个集合中获取公共元素。这里的 Intersect 方法很优雅。它可以用于多种类型的元素。
您的结果为空,因为它不是列表中的常用值。
List<string> lst = new List<string> { "abcXdef", "abcXdef", "abcede", "aYcde" };
List<string> num = new List<string> { "X", "Y", "abcXdef", "Z", "aYcde" };
var fin = lst.Intersect(num);
fin >> abcXdef,aYcde
您正在对两个列表进行交集,这将为您提供它们之间的共同项目。由于两个列表都不包含相同的项目,因此您得不到任何结果。
如果你想从 lst
中获取所有包含来自 num
的项目的项目,那么你可以执行类似下面的代码,它使用 string.Contains
方法来从 lst 过滤项目:
var fin = lst.Where(item => num.Any(item.Contains));
结果:
{ "abcXdef", "abcXdef", "aYcde" }
或者,如果您确实想执行不区分大小写的查询,您可以改用 IndexOf
方法:
var fin = lst.Where(item => num.Any(n =>
item.IndexOf(n, StringComparison.OrdinalIgnoreCase) >= 0));
如果这很难理解(有时 Linq 是),上面的第一个代码片段是 shorthand 编写以下内容的方式:
var fin = new List<string>();
foreach (var item in lst)
{
foreach (var n in num)
{
if (item.Contains(n))
{
fin.Add(item);
break;
}
}
}
当然,Rufus 已经在提供的答案中解决了您的问题。但是让我解释一下为什么您的方法不起作用。
它产生空结果的原因是因为 Equals(string x, string y)
永远不会被调用。它可以从 GetHashCode
方法中推断出不等式。如果哈希值相同,那么它将调用 Equals
。换句话说,你在 Equals
中的逻辑将永远不会被执行。
这是一些代码,您可以看到发生了什么。
class Program
{
static void Main(string[] args)
{
// See I added an item at the end here to show when Equals is called
List<string> lst = new List<string> { "abcXdef", "abcXdef", "abcede", "aYcde", "X" };
List<string> num = new List<string> { "X", "Y", "Z" };
var fin = lst.Intersect(num, new MiNumeroEqualityComparer()).ToList();
Console.ReadLine();
}
}
public class MiNumeroEqualityComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
Console.WriteLine("Equals called for {0} and {1}.", x, y);
return x.Contains(y);
}
public int GetHashCode(string obj)
{
Console.WriteLine("GetHashCode alled for {0}.", obj);
return obj.GetHashCode();
}
}
如果您 运行 上面的代码,它只会为产生相同散列的项目调用 Equals
;所以仅适用于 "X"。
查看 this fiddle 中的输出。