[英]IndexOf with custom StringComparer
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>
? 为什么
String.IndexOf(String, StringComparison)
需要StringComparison
而不允许更通用的StringComparer
,甚至不允许IComparer<T>
或IEqualityComparer<T>
?
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. 我创建了一个自定义的
StringComparer
来与几个字典一起使用,我想在项目的其他部分使用它,但是如果没有大量的扩展方法,我就找不到一个好的方法,如果那些甚至可以工作的话。
This is the comparer I made. 这是我制作的比较器。 It was based roughly on this recommendation: Implementing custom IComparer with string
它大致基于此建议: 使用字符串实现自定义IComparer
Also note that ModifyString is a WIP. 另请注意,ModifyString是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.
我也知道它很贵,但我只是在寻找解决方案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;
}
}
Using a convenient extension for IEnumerable
it seems like it should have already, you can write a String
extension to use a StringComparer
. 使用
IEnumerable
的方便扩展似乎它应该已经,你可以编写一个String
扩展来使用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. 正如注释中所建议的那样,所有可能的子串长度都在每个位置进行测试,因为不能对自定义
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 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
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.