首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有自定义IndexOf的StringComparer

带有自定义IndexOf的StringComparer
EN

Stack Overflow用户
提问于 2018-05-14 20:04:46
回答 2查看 372关注 0票数 3

为什么String.IndexOf(String, StringComparison)需要一个StringComparison,而不允许更一般的StringComparer,甚至只是IComparer<T>IEqualityComparer<T>

我做了一个定制的StringComparer,可以与几个字典一起使用,我想在我的项目的其他部分中使用它,但是如果不使用很多扩展方法,我就找不到一个很好的方法,如果这些方法都能工作的话。

这是我做的比较机。它大致基于以下建议:Implementing custom IComparer with string

还请注意,ModifyString是一个WIP。根据我正在比较的输入,我希望在那里添加更多的东西。我也知道它很贵,但我只是在寻找一种解决方案-- ATM,而不是性能。

代码语言:javascript
复制
public class CustomComparer : StringComparer
{
    public override int Compare(string x, string y)
    {
        return StringComparer.Ordinal.Compare(ModifyString(x), ModifyString(y));
    }

    public override bool Equals(string x, string y)
    {
        if (ModifyString(x).Equals(ModifyString(y)))
            return true;
        else
            return false;
    }

    public override int GetHashCode(string obj)
    {
        if (obj == null)
            return 0;
        else
            return ModifyString(obj).GetHashCode();
    }

    private string ModifyString(string s)
    {
        //I know this code is expensive/naaive, your suggestions are welcome.
        s = s.ToLowerInvariant();
        s = s.Trim();
        s = Regex.Replace(s, @"\s+", " ");//replaces all whitespace characters with a single space.
        return s;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-14 21:33:24

使用IEnumerable的方便扩展(似乎应该已经这样做了),您可以编写一个String扩展来使用StringComparer。正如注释中所建议的那样,所有可能的子字符串长度都会在每个位置进行测试,因为不能对自定义StringComparer做出任何假设。

代码语言:javascript
复制
public static class IEnumerableExt {
    public static T FirstOrDefault<T>(this IEnumerable<T> src, Func<T, bool> testFn, T defval) => src.Where(aT => testFn(aT)).DefaultIfEmpty(defval).First();
}

public static class StringExt {
    public static int IndexOf(this string source, string match, StringComparer sc) {
        return Enumerable.Range(0, source.Length) // for each position in the string
                         .FirstOrDefault(i => // find the first position where either
                             // match is Equal at this position for length of match (or to end of string) or
                             sc.Equals(source.Substring(i, Math.Min(match.Length, source.Length-i)), match) ||
                             // match is Equal to one of the substrings beginning at this position
                             Enumerable.Range(1, source.Length-i).Any(ml => sc.Equals(source.Substring(i, ml), match)),
                             -1 // else return -1 if no position matches
                          );
    }
}

注意:修改后可以正确处理源子字符串和匹配字符串长度可能不相等的情况。

票数 2
EN

Stack Overflow用户

发布于 2021-09-16 20:34:12

如果有人需要使用IComparer<String>的版本,下面是@NetMage发布的好解决方案的一个简单修改:

代码语言:javascript
复制
        public static int IndexOf(this string source, string match, IComparer<String> sc) {
        return Enumerable.Range(0, source.Length) // for each position in the string
            .FirstOrDefault(i => // find the first position where either
                    // match is Equal at this position for length of match (or to end of string) or
                    sc.Compare(source.Substring(i, Math.Min(match.Length, source.Length-i)), match) == 0 ||
                    // match is Equal to one of the substrings beginning at this position
                    Enumerable.Range(1, source.Length-i).Any(ml => sc.Compare(source.Substring(i, ml), match) == 0),
                -1 // else return -1 if no position matches
            );
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50338199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档