LINQ IEqualityComparer<string> 忽略大小写

9

我正在对元素列表进行排序:

var matchEle = listOfElements.Where(e => e.Properties().Any(p => p.Name.Contains("Key", Asking for IEqualityComparer))).First();

我通常直接使用StringComparer.OrdinalIgnoreCase或StringComparer.CurrentCultureIgnoreCase,但在调用Contains()时,它要求传入一个IEqualityComparer。我猜想这是因为数据结构/层次的原因。我看到了一个如何设置IEqualityComparer的示例,例如:

strEqualityComparer = new IEqualityComparer();

我需要定义一个用于 strEqualityComparer 类的类,但除此之外我不太确定。有人能帮我让我的 linq 语句忽略大小写并正常工作吗?请注意,以下是数据结构示例:

listOfElements = [element1, element2, etc..]
element1.Properties = ["Prop1", "Key1", "Prop2", "Key2", etc.]

如果任何属性的值包含关键词(在这种情况下为 "Key"),则需要提取通过过滤器的元素,因此它不能是.Equals或IndexOf。

如果“Name”是一个字符串,你不需要使用“contains”,只需要使用“Equals”并忽略大小写。但是,如果你将查询更改为:“(e => e.Properties().Select(p => p.Name).Contains("Key"))”,你需要在这里使用自定义比较器。 - Mohammed Sajid
@GertArnold 我相信 .Net 4.8。 - AndyBernard
那么就没有接受stringIEqualityComparerContains方法。由于它基于IEnumerable,出于某种奇怪的原因,只有一个char + IEqualityComparer的重载。 - Gert Arnold
将您的问题标记为此问题的重复:https://dev59.com/D3RB5IYBdhLWcg3w-8Lo。 - Gert Arnold
嘿 @GertArnold,我必须说这是我第一次看到IndexOf被用作Contains函数。我有点困惑了。我一直以为IndexOf是在寻找确切项的索引,但在你提到的例子以及Sajid的例子中,IndexOf被用于查找包含所提供键的项的索引。因此,从根本上讲,我的问题是,IndexOf()是否返回包含所提供键的项的第一个出现而不是等于所提供键的项? - AndyBernard
1个回答

10

根据评论更新

在另一个字符串中搜索 string

var matchEle = listOfElements
.Where(e => e.Properties().Any(p => p.Name.IndexOf("Key", System.StringComparison.OrdinalIgnoreCase) >= 0))
.First();

旧解决方案

你有两个选项,取决于 Name 的类型:
1-如果NameProperties中是一个string,且没有使用IEqualityComparer,请用Equals代替Contains。例如:

var matchEle = listOfElements
    .Where(e => e.Properties().Any(p => p.Name.Equals("Key", StringComparison.OrdinalIgnoreCase)))
    .First();

2 - 使用 IEqualityComparer,并且如果 Properties 中的 Namestring 的列表:
2.1:创建一个自定义比较器,例如:

public class StringIEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Equals(y, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(string obj)
    {
        return obj.GetHashCode();
    }
}

2.2: 将您的查询略作更改:

var matchEle = listOfElements
.Where(e => e.Properties().Any(p => p.Name.Contains("Key", new StringIEqualityComparer())))
.First();

希望这可以帮助到您。


嘿@Sajid 感谢您的回复。实际上,我已经按照您在此帖子之前所写的方式设置了自己的IEqualityComparer。但是当我使用它时,Visual Studio会抛出一个异常,Null异常,“Contains”没有重载方法接受2个参数,即使通过智能感知它显示添加IEqualityComparer的选项。 - AndyBernard
我也不能使用Equals,因为不幸的是我没有提供一个精确的键来匹配,我需要筛选出包含关键字的特定字符串。 - AndyBernard
如果我理解正确,您正在搜索3D选项,并在字符串中搜索某些字符串? - Mohammed Sajid
@AndyBernard:对于第一个评论,这是正常的,因为所提议的比较器是针对“char”而不是“string”的。 - Mohammed Sajid
2
请注意,此实现违反了在HashSet中使用的合同,因为相等的对象并不总是返回相等的哈希码。一个次优的解决方法是在GetHashCode中对obj执行ToLower操作,以便考虑大小写不敏感性。对于OP用例,这不是一个问题,但对于其他人尝试在一般情况下使用它的人来说,这是一个注意事项。 - GameSalutes
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接