मेरे पास एक आवश्यकता है जो अपेक्षाकृत अस्पष्ट है, लेकिन यह महसूस करता है कि बीसीएल का उपयोग करना संभव होना चाहिए।
संदर्भ के लिए, मैं Noda Time में दिनांक / समय स्ट्रिंग को पार्स कर रहा हूं । मैं इनपुट स्ट्रिंग के भीतर अपनी स्थिति के लिए एक तार्किक कर्सर बनाए रखता हूं। तो जबकि पूरा स्ट्रिंग "3 जनवरी 2013" हो सकता है, तार्किक कर्सर 'J' पर हो सकता है।
अब, मुझे महीने के नाम को पार्स करने की आवश्यकता है, संस्कृति के सभी ज्ञात महीनों के नामों की तुलना करते हुए:
- संस्कृति संवेदनशीलता
- केस-insensitively
- कर्सर के बिंदु से (बाद में नहीं; मैं देखना चाहता हूं कि क्या कर्सर उम्मीदवार महीने का नाम "देख रहा है")
- जल्दी से
- ... और मुझे यह जानने की आवश्यकता है कि कितने वर्णों का उपयोग किया गया था
यह करने के लिए वर्तमान कोड आम तौर पर काम करता है, का उपयोग कर 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))
परंतु:
- इसके लिए मुझे एक विकल्प बनाना होगा, जिससे मैं वास्तव में बचूँ। (मैं नोडा टाइम को प्रभावी रूप से एक सिस्टम लाइब्रेरी के रूप में देख रहा हूं; कुछ ग्राहकों के लिए प्रदर्शन का प्रदर्शन महत्वपूर्ण हो सकता है।)
- यह मुझे नहीं बताता कि बाद में कर्सर को कैसे आगे बढ़ाना है
वास्तव में, मुझे दृढ़ता से संदेह है कि यह बहुत बार नहीं आएगा ... लेकिन मैं वास्तव में यहां सही काम करना चाहूंगा । मैं भी वास्तव में एक यूनिकोड विशेषज्ञ बनने के बिना या खुद इसे लागू करने में सक्षम होना चाहूंगा :)
( यदि कोई भी अंतिम निष्कर्ष का पालन करना चाहता है, तो नोडा टाइम में बग 210 के रूप में उठाया गया ।)
मुझे सामान्यीकरण का विचार पसंद है। मुझे यह जांचने की आवश्यकता है कि ए) शुद्धता और बी) प्रदर्शन के लिए विस्तार से। यह मानते हुए कि मैं इसे सही ढंग से काम कर सकता हूं , मुझे अभी भी यकीन नहीं है कि यह कैसे बदल जाएगा या नहीं - यह उस तरह की चीज है जो वास्तव में वास्तविक जीवन में कभी नहीं आएगी, लेकिन मेरे सभी उपयोगकर्ताओं के प्रदर्शन को चोट पहुंचा सकती है: (
मैंने 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");
}
}
}
कस्टम महीने के नाम को "बेड" के पाठ मान के साथ सिर्फ "बेड" में बदलना ठीक है।
ठीक है, कुछ और डेटा बिंदु:
उपयोग करने की लागत
SubstringऔरIsPrefixमहत्वपूर्ण है लेकिन भयानक नहीं है। मेरे विकास लैपटॉप पर "शुक्रवार 12 अप्रैल 2013 20:28:42" के नमूने में, यह पार्स संचालन की संख्या को बदलता है जिसे मैं एक सेकंड में लगभग 460K से लगभग 400K तक निष्पादित कर सकता हूं। यदि संभव हो तो मैं उस मंदी से बचना चाहता हूँ, लेकिन यह बहुत बुरा नहीं है ।मेरे विचार से सामान्यीकरण कम संभव है - क्योंकि यह पोर्टेबल कक्षा पुस्तकालयों में उपलब्ध नहीं है। मैं संभवतः यह इस्तेमाल कर सकते हैं सिर्फ गैर पीसीएल बनाता है के लिए, पीसीएल की इजाजत दी थोड़ा कम सही होने के लिए बनाता है। सामान्यीकरण के लिए परीक्षण का प्रदर्शन हिट (
string.IsNormalized) प्रति सेकंड लगभग 445K कॉल के लिए प्रदर्शन लेता है, जिसके साथ मैं रह सकता हूं। मुझे अभी भी यकीन नहीं है कि मुझे वह सब कुछ करना है जो मुझे इसकी आवश्यकता है - उदाहरण के लिए, एक महीने का नाम "sure" होना चाहिए जो कई संस्कृतियों में "एसएस" से मेल खाना चाहिए, मेरा मानना है ... और सामान्यीकरण ऐसा नहीं करता है।
textसमय बहुत लंबा नहीं है, तो आप कर सकते हैं if (compareInfo.IndexOf(text, candidate, position, options) == position)। msdn.microsoft.com/en-us/library/ms143031.aspx लेकिन अगर textयह बहुत लंबा है, तो यह खोज करने में बहुत समय बर्बाद करने वाला है कि इसे कहां तक पहुंचाना है।
Stringवर्ग सभी को इस उदाहरण में और एक का उपयोग Char[]सीधे। आप अधिक कोड लिखना समाप्त कर देंगे, लेकिन ऐसा तब होता है जब आप उच्च प्रदर्शन चाहते हैं ... या हो सकता है कि आप C ++ / CLI ;-) में प्रोग्रामिंग कर रहे हों