나는 상대적으로 불분명 요구 사항을 가지고 있지만, 그것은 것처럼 느낀다 해야 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을 효과적으로 시스템 라이브러리로보고 있으며, 일부 클라이언트에게는 구문 분석 성능이 중요 할 수 있습니다.)
- 나중에 커서를 얼마나 멀리 이동할지 알려주지 않습니다.
실제로, 나는 강하게이 매우 자주 오지 않습니다 의심 ...하지만 난 정말 것 처럼 여기 옳은 일을 할 수 있습니다. 유니 코드 전문가가 아니거나 직접 구현하지 않고도 할 수 있기를 바랍니다. :)
( 누군가가 궁극적 인 결론을 따르기를 원할 경우 Noda Time에서 버그 210으로 발생 했습니다.)
나는 정규화라는 아이디어를 좋아합니다. a) 정확성 및 b) 성능에 대해 자세히 확인해야합니다. 제대로 작동 할 수 있다고 가정 할 때 , 모든 것을 바꿀 가치가 있는지는 아직 확실하지 않습니다 . 실제 생활에서 실제로는 나오지 않을 것이지만 모든 사용자의 성능을 저하시킬 수 있습니다. (
나는 또한 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
큰하지만 끔찍한하지 않습니다. 내 개발 노트북의 "Friday April 12 2013 20:28:42"샘플에서 1 초에 실행할 수있는 구문 분석 작업 수를 약 460K에서 약 400K로 변경합니다. 가능하면 속도 저하를 피하고 싶지만 그렇게 나쁘지는 않습니다.정규화는 이식 가능한 클래스 라이브러리에서 사용할 수 없기 때문에 생각보다 덜 실현 가능합니다. 나는 잠재적 으로 비 PCL 빌드 에만 사용할 수 있으므로 PCL 빌드가 약간 덜 정확할 수 있습니다. 정규화 테스트 (
string.IsNormalized
)의 성능 저하로 인해 성능이 초당 약 44 만 5 천 호출로 저하되며,이를 감안할 수 있습니다. 예를 들어, "ß"를 포함하는 월 이름은 많은 문화권에서 "ss"와 일치해야한다고 생각합니다. 정규화는 그렇게하지 않습니다.
text
너무 오래하지, 당신은 할 수 있었다 if (compareInfo.IndexOf(text, candidate, position, options) == position)
. msdn.microsoft.com/en-us/library/ms143031.aspx 하지만 text
너무 길면 필요한 곳을 넘어 검색하는 데 많은 시간을 낭비하게됩니다.
String
클래스를 전혀 이 경우와 사용 Char[]
직접. 더 많은 코드를 작성하게 되겠지만 고성능을 원하거나 C ++ / CLI로 프로그래밍해야 할 때 발생합니다. ;-)