У меня есть требование, которое относительно неясное, но похоже, что это возможно, используя BCL.
В контексте я разбираю строку даты/времени в Noda Time. Я поддерживаю логический курсор для своей позиции во входной строке. Таким образом, хотя полная строка может быть "3 января 2013 года", логический курсор может находиться в "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 или не выполнив его сам:)
(Поднято как ошибка 210 в Noda Time, если кто-то захочет следовать любому возможному завершению.)
Мне нравится идея нормализации. Мне нужно проверить, что подробно для a) правильности и б) производительности. Предполагая, что я могу заставить его работать правильно, я все еще не уверен, как это стоило бы изменить все - это то, что, вероятно, никогда не появится в реальной жизни, но может повредить производительность всех моих пользователей: (
Я также проверил 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" отлично обрабатывается.
Хорошо, еще несколько точек данных:
-
Стоимость использования
Substring
иIsPrefix
значительна, но не ужасна. На образце "Friday April 12 2013 20:28:42" на моем ноутбуке разработки он меняет количество операций синтаксического анализа, которые я могу выполнить за секунду от примерно 460K до примерно 400K. Я бы предпочел избежать этого замедления, если это возможно, но это не так уж плохо. -
Нормализация менее осуществима, чем я думал, потому что она недоступна в портативных библиотеках классов. Я мог бы использовать его только для сборки, отличной от PCL, что позволяет строить PCL немного менее корректно. Достижение производительности при тестировании для нормализации (
string.IsNormalized
) имеет производительность вплоть до 445 тыс. Вызовов в секунду, с которой я могу жить. Я все еще не уверен, что он делает все, в чем я нуждаюсь, например, название месяца, содержащее "ß", должно соответствовать "ss" во многих культурах, я полагаю... и нормализация этого не делает.