2010-03-09 17 views
6

बू आ रही है नीचे दिए गए कोड में एक स्ट्रिंग लेने के लिए और मनमाने ढंग से शब्द का एक सेट है कि एक खोज वाक्यांश के गैर जरूरी माना जाता है के किसी भी दूर करने के लिए बनाया गया है।नेट स्ट्रिंग को पार्स प्रदर्शन में सुधार - संभव कोड

मैं कोड नहीं लिखा था, लेकिन कुछ और में शामिल करने की जरूरत है। यह काम करता है, और यह अच्छा है, लेकिन यह मेरे लिए गलत लगता है। हालांकि, मुझे बॉक्स के बाहर अपना सिर नहीं मिल रहा है कि इस विधि ने एक और दृष्टिकोण के बारे में सोचने के लिए बनाया है।

शायद मैं इसे जितना जटिल होना चाहता हूं उससे अधिक जटिल बना रहा हूं, लेकिन मुझे लगता है कि यह LINQ का उपयोग कर एक अलग तकनीक के साथ क्लीनर हो सकता है।

मैं किसी भी सुझाव का स्वागत करेंगे; जिसमें सुझाव है कि मैं इसे सोच रहा हूं और यह कि मौजूदा कोड पूरी तरह स्पष्ट, संक्षिप्त और निष्पादक है।

private string RemoveNonEssentialWords(string phrase) 
{ 
    //This array is being created manually for demo purposes. In production code it's passed in from elsewhere. 
    string[] nonessentials = {"left", "right", "acute", "chronic", "excessive", "extensive", 
            "upper", "lower", "complete", "partial", "subacute", "severe", 
            "moderate", "total", "small", "large", "minor", "multiple", "early", 
            "major", "bilateral", "progressive"}; 
    int index = -1; 

    for (int i = 0; i < nonessentials.Length; i++) 
    { 
     index = phrase.ToLower().IndexOf(nonessentials[i]); 
     while (index >= 0) 
     { 
      phrase = phrase.Remove(index, nonessentials[i].Length); 
      phrase = phrase.Trim().Replace(" ", " "); 
      index = phrase.IndexOf(nonessentials[i]); 
     } 
    } 

    return phrase; 
} 

आपकी मदद के लिए अग्रिम धन्यवाद:

तो, यहाँ कोड है।

चीयर्स,

स्टीव

उत्तर

11

यह एक खोज वाक्यांश से स्टॉप शब्दों को हटाने के लिए एक एल्गोरिदम प्रतीत होता है।

यहां एक विचार है: यदि वास्तव में यह खोज के लिए उपयोग किया जा रहा है, तो क्या आपको परिणामी वाक्यांश को मूल (सभी मूल सफेद जगहों के साथ) का सही प्रतिनिधित्व करने की आवश्यकता है, लेकिन स्टॉप शब्दों को हटाकर, या कर सकते हैं "पर्याप्त पास" हो ताकि परिणाम अभी भी प्रभावी हों?

एक दृष्टिकोण वाक्यांश tokenize होगा (अपनी पसंद के दृष्टिकोण का उपयोग कर - एक regex हो सकता है, मैं एक साधारण विभाजन का उपयोग करेंगे) और फिर हटा दिया रोक शब्दों के साथ यह पुनः। उदाहरण:

public static string RemoveStopWords(string phrase, IEnumerable<string> stop) 
{ 
    var tokens = Tokenize(phrase); 
    var filteredTokens = tokens.Where(s => !stop.Contains(s)); 
    return string.Join(" ", filteredTokens.ToArray()); 
} 

public static IEnumerable<string> Tokenize(string phrase) 
{ 
    return string.Split(phrase, ' '); 
    // Or use a regex, such as: 
    // return Regex.Split(phrase, @"\W+"); 
} 

यह आपको बिल्कुल ही परिणाम प्राप्त नहीं होगा, लेकिन मुझे यकीन है चल जाएगा कि यह काफी करीब है और यह निश्चित रूप से और अधिक कुशलता से एक बहुत चलेंगे। वास्तविक खोज इंजन इस तरह के दृष्टिकोण का उपयोग करते हैं, क्योंकि सब कुछ अनुक्रमित होता है और शब्द स्तर पर खोजा जाता है, चरित्र स्तर नहीं।

+0

मैं भी इनपुट को अलग शब्दों में विभाजित करना पसंद करता हूं। प्रत्येक खोज शब्द पर भावी तर्क लागू करने के लिए भी उपयोगी होगा। जैसे वर्तनी जांच –

+1

यदि प्रदर्शन को अधिकतम करने की आवश्यकता है, तो यह कहने योग्य है कि इस विधि में अभी भी बहुत अक्षमता है। इनपुट स्ट्रिंग को टॉकनाइज करना, स्पष्ट रूप से, कई स्ट्रिंग्स के रूप में बनाएगा क्योंकि इनपुट स्ट्रिंग में शब्द हैं। साथ ही, सरणी बनाने और शब्दों को दोबारा जोड़ने में कुछ समय लग सकता है यदि इनपुट बड़ा है। –

+2

@qstarin: यह मानते हुए कि एक खोज वाक्यांश से अधिक होने की संभावना नहीं है, ओह, लगभग 10 शब्द या तो, मुझे संदेह है कि यह एक महत्वपूर्ण समस्या उत्पन्न करने जा रहा है।'स्टॉप' तर्क के लिए 'हैशसेट ' पास करें और यह शब्दों की संख्या से ओ (एन) बन जाता है; इस बिंदु से परे प्रदर्शन के बारे में चिंता करना समयपूर्व अनुकूलन आईएमओ बन जाता है। स्वच्छ, पठनीय कोड के लिए लक्ष्य जो * उचित * पहले प्रदर्शन करता है; फिर, यदि यह पर्याप्त नहीं है, तो आप माइक्रो-ऑप्टिमाइज़ेशन बनाना शुरू कर सकते हैं। – Aaronaught

3

मैं इस कार्य के लिए (समारोह के अंदर बनाई गई) रेगुलर एक्सप्रेशन का उपयोग होगा। मुझे लगता है कि यह स्ट्रिंग के माध्यम से एकाधिक पास करने या एकाधिक मध्यवर्ती तार बनाने के बिना एक ही समय में सभी प्रसंस्करण करने में सक्षम होगा।

private string RemoveNonEssentialWords(string phrase) 
{ 
    return Regex.Replace(phrase, // input 
         @"\b(" + String.Join("|", nonessentials) + @")\b", // pattern 
         "", // replacement 
         RegexOptions.IgnoreCase) 
      .Replace(" ", " "); 
} 

\b शुरुआत और पैटर्न के अंत में यह सुनिश्चित करें कि मैच अक्षरांकीय और गैर अक्षरांकीय अक्षर के बीच सीमा पर है बनाता है। दूसरे शब्दों में, यह शब्द के केवल भाग से मेल नहीं खाएगा, जैसे आपका नमूना कोड करता है।

+0

हालांकि आपको शब्द सूची के आधार पर गतिशील रूप से नियमित अभिव्यक्ति बनाना होगा, क्योंकि यह उत्पादन संस्करण में फ़ंक्शन के लिए पैरामीटर है, और निरंतर सरणी नहीं है। –

1

हाँ, यह बदबू आ रही है।

मुझे पार्सिंग के लिए छोटी राज्य मशीन पसंद है, वे प्रतिनिधियों की सूचियों का उपयोग करके एक विधि के अंदर स्वयं निहित हो सकते हैं, इनपुट में वर्णों के माध्यम से लूपिंग कर सकते हैं और राज्य कार्यों के माध्यम से प्रत्येक को भेज सकते हैं (जिसे मैंने अगले राज्य समारोह को वापस कर दिया है जांच चरित्र के आधार पर)।

प्रदर्शन के लिए मैं एक स्ट्रिंग बिल्डर के लिए पूरे शब्द बाहर फ्लश के बाद मैं एक विभाजित करने चरित्र मारा और सूची के खिलाफ शब्द देख लिया है

5

मुझे लगता है कि अपने कोड नहीं है (उस के लिए एक हैश सेट का उपयोग कर सकते हैं) वही करना जो आप चाहते हैं कि वैसे भी करें। यदि मैं सही हूं तो "नियंत्रित" को "डी" में परिवर्तित कर दिया जाएगा। एक अच्छा समाधान प्राप्त करने के लिए आपको अपनी आवश्यकताओं को थोड़ा अधिक विस्तृत करना होगा। मैं शायद प्रतिस्थापन या नियमित अभिव्यक्तियों का उपयोग करता हूं।

+0

मैं बस इसे इंगित करने जा रहा था, लेकिन 'बायी' से 'y' का उपयोग कर रहा था। – Mark

+0

मैंने कोड दोष पर भी उठाया। एक स्ट्रिंग के रूप में वाक्यांश पर काम करने के बजाय, इसे शब्दों के एक सेट के रूप में छेड़छाड़ करने की आवश्यकता होगी। –

+0

यदि वाक्यांश में "lefacutet" प्रकट होता है, तो यह "तीव्र" को हटा देगा और "बाएं" छोड़ देगा, भले ही "बाएं" एक अनिवार्य है। – Brian

1

मैं हटाए गए शब्दों की एक हैश तालिका प्रत्येक शब्द को पार्स कर दूंगा यदि हैश में इसे केवल एक बार सरणी के माध्यम से हटा दें और मेरा मानना ​​है कि एक तालिका बनाना ओ (एन) है।

0

यह कैसे दिखता है?

 foreach (string nonEssent in nonessentials) 
     { 
      phrase.Replace(nonEssent, String.Empty); 
     } 
     phrase.Replace(" ", " "); 
+2

यह मूल कोड के समान ही काम करता है, फिर भी अन्य पोस्टर्स ने मूल कोड के साथ इंगित की गई सभी समस्याओं से पीड़ित है, लेकिन यह क्लीनर और पढ़ने में आसान है। एक पार्सर/राज्य मशीन जो शब्दों में इनपुट को विभाजित करती है वह समग्र रूप से बेहतर हो सकती है। –

0

यदि आप रेगेक्स मार्ग जाना चाहते हैं, तो आप इसे ऐसा कर सकते हैं। यदि आप गति के लिए जा रहे हैं तो यह एक कोशिश के लायक है और आप अन्य विधियों के साथ तुलना/विपरीत कर सकते हैं:

सरणी इनपुट से रेगेक्स बनाकर प्रारंभ करें। कुछ की तरह:

var regexString = "\\b(" + string.Join("|", nonessentials) + ")\\b"; 

ऐसा ही कुछ में परिणाम होगा:

\ b (बाएं | सही | जीर्ण) \ b

तो खोज करने के लिए एक Regex वस्तु बनाने/बदलें:

System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(regexString, System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

तो फिर तुम बस ऐसा कर सकते हैं की तरह एक बदलें:

+०१२३५१६४१०६
string fixedPhrase = regex.Replace(phrase, ""); 
संबंधित मुद्दे