c# - IndexOf 与自定义 StringComparer

标签 c# string comparison

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

我定制了一个StringComparer与多个词典一起使用,我想在我的项目的其他部分使用它,但如果不做很多扩展方法,我找不到一个好的方法来做到这一点,如果这些方法可行的话。

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

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

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;
    }
}

最佳答案

使用 IEnumerable 的方便扩展似乎应该已经有了,您可以编写一个 String 扩展来使用 StringComparer。正如评论中所建议的,所有可能的子字符串长度都在每个位置进行测试,因为无法对自定义 StringComparer 进行假设。

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
                          );
    }
}

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

关于c# - IndexOf 与自定义 StringComparer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50338199/

相关文章:

C# 从列表框中删除项目

java - 将逗号分隔的字符串转换为整数数组的最佳方法

java - 哪些设置会影响已编译的 java .class 文件的布局?你怎么知道两个编译类是否相等?

c++ - C++ 标准中 pair<> 的全局不等式比较

c# - 在 ASP.NET 自动回发之前更改下拉项目文本

c# - WPF 窗体的布局 - 水平列表框

c# - 字符串被神秘地切断

html - NSAttributedstring 到 HTML

java - 比较两个版本字符串(4.x.x.x、5.x.x.x)

Spring 与 Jboss