我有一个相对模糊的要求,但感觉应该可以使用BCL。
对于上下文,我正在解析Noda Time中的日期/时间字符串。我在输入字符串中的位置保持逻辑光标。因此,尽管完整的字符串可能是“ 2013年1月3日”,但逻辑光标可能位于“ J”处。
现在,我需要解析月份名称,并将其与区域性的所有已知月份名称进行比较:
- 文化敏感
- 不区分大小写
- 只是从光标的位置开始(不晚;我想查看光标是否正在“查看”候选月份名称)
- 很快
- ...然后我需要知道使用了多少个字符
使用的当前代码通常可以正常运行CompareInfo.Compare
。实际上是这样的(仅适用于匹配部分-真实代码中有更多代码,但与匹配无关):
internal bool MatchCaseInsensitive(string candidate, CompareInfo compareInfo)
{
return compareInfo.Compare(text, position, candidate.Length,
candidate, 0, candidate.Length,
CompareOptions.IgnoreCase) == 0;
}
但是,这取决于候选对象和我们比较的区域具有相同的长度。在大多数情况下都可以,但是在某些特殊情况下不可以。假设我们有这样的东西:
// U+00E9 is a single code point for e-acute
var text = "x b\u00e9d y";
int position = 2;
// e followed by U+0301 still means e-acute, but from two code points
var candidate = "be\u0301d";
现在,我的比较将失败。我可以使用IsPrefix
:
if (compareInfo.IsPrefix(text.Substring(position), candidate,
CompareOptions.IgnoreCase))
但:
- 这需要我创建一个子字符串,我确实希望避免这样做。(我将Noda Time视为有效的系统库;解析性能对于某些客户端可能很重要。)
- 它没有告诉我事后将光标前进多远
实际上,我强烈怀疑这种情况不会经常出现……但是我真的很想在这里做正确的事。我也很想能够做到这一点,而无需成为Unicode专家或自己实现它:)
(在Noda Time中作为bug 210引发,以防万一有人想遵循任何最终结论。)
我喜欢规范化的想法。我需要详细检查a)正确性和b)性能。假设我可以使其正常运行,我仍然不确定是否值得一揽子改变-这种事情在现实生活中可能永远不会真正出现,但是会损害我所有用户的性能: (
我还检查了BCL-似乎也无法正确处理此BCL。样例代码:
using System;
using System.Globalization;
class Test
{
static void Main()
{
var culture = (CultureInfo) CultureInfo.InvariantCulture.Clone();
var months = culture.DateTimeFormat.AbbreviatedMonthNames;
months[10] = "be\u0301d";
culture.DateTimeFormat.AbbreviatedMonthNames = months;
var text = "25 b\u00e9d 2013";
var pattern = "dd MMM yyyy";
DateTime result;
if (DateTime.TryParseExact(text, pattern, culture,
DateTimeStyles.None, out result))
{
Console.WriteLine("Parsed! Result={0}", result);
}
else
{
Console.WriteLine("Didn't parse");
}
}
}
将自定义月份的名称更改为文本值为“ bEd”的“ bed”即可。
好的,还有几个数据点:
使用
Substring
和的成本很高,IsPrefix
但并不可怕。在我的开发笔记本电脑上的示例“ 2013年4月12日星期五20:28:42”上,它将我可以执行的每秒解析操作的次数从大约460K更改为大约400K。如果可能的话,我宁愿避免这种速度下降,但是还算不错。标准化比我想象的要难-因为在可移植类库中不可用。我可能会将其仅用于非PCL构建,从而使PCL构建的正确性稍差一些。测试归一化(
string.IsNormalized
)的性能影响使性能降低到每秒约44.5万次调用,我可以忍受。我仍然不确定它是否可以完成我需要做的所有事情-例如,在许多文化中,包含“ß”的月份名称应与“ ss”匹配,我相信...而规范化并不能做到这一点。
text
的时间不太长,可以这样做if (compareInfo.IndexOf(text, candidate, position, options) == position)
。msdn.microsoft.com/zh-cn/library/ms143031.aspx 但是,如果text
时间太长,那将浪费大量时间进行超出所需位置的搜索。
String
该类并直接使用a 。您最终将编写更多的代码,但这就是当您想要高性能时会发生的事情……或者您应该使用C ++ / CLI进行编程;-)Char[]