本文介绍了具有自定义StringComparer的IndexOf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Why does String.IndexOf(String, StringComparison) require a StringComparison and not allow for the more general StringComparer, or even just IComparer<T> or IEqualityComparer<T>?

我制作了一个自定义 StringComparer 可以与多个词典一起使用,我想在其他词典中使用它我的项目的一部分,但是如果没有很多扩展方法,我将找不到一个好的方法,如果这些方法甚至可行的话。

I made a custom StringComparer to use with several dictionaries, and I want to use it in other parts of my project but I can't find a good way to do that without making lots of extensions methods, if those would even work.

这是我做的比较器。它大致基于以下建议:

This is the comparer I made. It was based roughly on this recommendation: Implementing custom IComparer with string

还要注意ModifyString是一个WIP。我希望根据与之比较的输入在此处添加更多内容。我也知道这很昂贵,但是我只是在寻找解决方案的ATM,而不是性能。

Also note that ModifyString is a WIP. I expect to add more things there, based on the input that I'm comparing against. I also know that it's expensive, but I'm just looking for a solution ATM, not performance.

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 进行任何假设,所以会在每个位置测试所有可能的子字符串长度。

Using a convenient extension for IEnumerable it seems like it should have already, you can write a String extension to use a StringComparer. As suggested in a comment, all possible substring lengths are tested at each position since no assumption about the custom StringComparer can be made.

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 Equals 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 Equals to on of the substrings beginning at this position
                             Enumerable.Range(1, source.Length-i-1).Any(ml => sc.Equals(source.Substring(i, ml), match)),
                             -1 // else return -1 if no position matches
                          );
    }
}

这篇关于具有自定义StringComparer的IndexOf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 00:09