2012-04-11 21 views
5

मैं एक स्ट्रिंग किसी भी शब्द कसम खाता शामिल है कि क्या जांच करने की आवश्यकता में तार का एक सेट में से एक को खोजने के लिए सबसे तेज़ तरीका। अबसी # - एक और स्ट्रिंग

HashSet<string> swearWords = new HashSet<string>() { "word_one", "word_two", "etc" }; 

मैं अगर swearWords में निहित मूल्यों के किसी भी मेरी स्ट्रिंग में हैं देखने की जरूरत:

एक और सवाल यहां से कुछ सलाह के बाद, मैं एक HashSet शब्दों से युक्त कर दिया।

मैंने देखा है यह इसका उल्टा किया, जैसे:

swearWords.Contains(myString) 

लेकिन यह अवास्तविक लौटाते हैं।

जाँच करने के लिए करता है, तो HashSet वाला कोई भी शब्द myString में हैं सबसे तेज़ तरीका क्या है?

एनबी: मैं समझ मैं बदले में प्रत्येक शब्द की जाँच करने के लिए, और तोड़ने यदि मिलान हो जाता है, मैं बस हो, तो एक तेज़ तरीका सोच रहा हूँ एक foreach पाश का उपयोग कर सकते हैं।

+0

साथ आप क्यों कर रहे हैं किसी भी मिलान हैं 'हैशसेट' का उपयोग कर? यहां 'सूची ' का उपयोग करना आसान हो सकता है। और उसके बाद 'myString' को एक सूची में विभाजित करें और आवश्यक तुलना करें। – SkonJeet

+1

@SkonJeet: यदि शब्द की कसम सूची बड़ी है, रोकथाम के लिए जाँच तेजी से एक 'List' की तुलना में एक' HashSet' के लिए किया जाएगा - और मैं नहीं देख सकता है कि एक 'List' यह किसी भी * आसान बनाना होगा *। –

+0

मैं मूल रूप से एक सूची का उपयोग किया गया था और फिर इसे एक HashSet में बदला के रूप में मैंने पढ़ा है वे – surfitscrollit

उत्तर

6

आप एक regex की कोशिश कर सकते हैं, लेकिन मुझे यकीन है कि यह है नहीं कर रहा हूँ और तेज।

Regex rx = new Regex("(" + string.Join("|", swearWords) + ")"); 
rx.IsMatch(myString) 
+2

+1! (foreach प्रभावी रूप से प्रगणक अंदर छुपा के साथ।) - कसम बस शब्द सबसे अच्छा नियमित अभिव्यक्ति के रूप में वर्णित किया जाता है। मैं अपने अनुभव से बात कर रहा हूँ। हालांकि, यह व्यावहारिक रूप से असंभव एक स्थिर एल्गोरिथ्म और एक शब्द सूची के साथ उपयोगकर्ताओं को हराया है। –

9

आप को लागू करने कंटेनर एक IEnumerable < में अपने शपथ जगह>:

var containsSwears = swarWords.Any(w => myString.Contains(w)); 

नोट: HashSet <> IEnumerable लागू करता <>

+2

'HashSet ' लागू 'IEnumerable ' करता है। (और तुम तो आप इस दृष्टिकोण का उपयोग कर रहे हैं Scunthorpe समस्या के लिए बाहर देखने की जरूरत है: http://en.wikipedia.org/wiki/Scunthorpe_problem) – LukeH

+0

@LukeH: अच्छा बिंदु लेकिन इस चर्चा के दायरे से बाहर। सवाल पर एक टिप्पणी के रूप में शायद बेहतर है। +1 – Sprague

+0

लॉल @ स्कन्थोरपे, अच्छा नाम। हालांकि यदि शब्दों को तोड़ने के लिए आपका तर्क काम करता है तो आपको उस समस्या से स्पष्ट होना चाहिए क्योंकि आप पूरे शब्दों की जांच कर रहे हैं, शब्दों के भीतर तार नहीं। आपके पास एक समस्या हो सकती है जो लीट बोलने वाले शब्दों या शब्दों की केस-संवेदनशीलता से मेल खाती है। –

3

आप एक IEnumerable प्रकार में "myString" विभाजित कर सकते हैं, और फिर उन पर "ओवरलैप नहीं" का उपयोग करें?

http://msdn.microsoft.com/en-us/library/bb355623(v=vs.90).aspx

(पी एस लंबे समय नहीं देख ...)

संपादित: मेरे पिछले जवाब में बस देखा त्रुटि।

+0

अरे एडम! हाँ यह हे – surfitscrollit

+0

वास्तव में है, मैंने डबल चेक किया गया, ओवरलैप ऐसा लगता है कि आपको वास्तव में वही करना चाहिए जो आपको चाहिए? हालांकि दक्षता पर निश्चित नहीं है। – KingCronus

6

आप शब्दों कसम खाता हूँ आप Aho-Corasick एल्गोरिथ्म इस्तेमाल कर सकते हैं की बहुत बड़ी सेट किया हुआ है: http://tomasp.net/blog/ahocorasick.aspx

3

मुख्य समस्या ऐसी योजनाओं के साथ है परिभाषित करने के लिए क्या एक शब्द स्ट्रिंग आप जाँच करना चाहते हैं के संदर्भ में है ।

ऐसे input.Contains का उपयोग कर बस एक शब्द की अवधारणा नहीं है उन लोगों के रूप
  • अनुभवहीन कार्यान्वयन; वे "का पता लगाने" शब्द तब भी जब कि आशय नहीं था कसम खाता हूँ जाएगा।
  • खाली स्थान के पर ब्रेकिंग शब्द यह (भी विराम चिह्न, आदि पर विचार करें) काटने के लिए नहीं जा रहा है। खाली स्थान के अलावा अन्य पात्रों पर
  • ब्रेकिंग संस्कृति मुद्दों को उठाने जा रहा है: क्या वर्ण शब्द-वर्ण माना जाता है वास्तव में?

मान लें कि आपकी स्टॉपवर्ड सूची केवल लैटिन वर्णमाला का उपयोग करती है, एक व्यावहारिक विकल्प यह मानना ​​होगा कि शब्द केवल लैटिन वर्णों के अनुक्रम हैं।तो कोई उचित शुरुआती समाधान

var words = Regex.Split(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Pc}\p{Lm}]", myString); 

regex ऊपर मानक वर्ग \W अंक शामिल नहीं करने के लिए संशोधित है हो सकता है; अधिक जानकारी के लिए, http://msdn.microsoft.com/en-us/library/20bw873z.aspx देखें। अन्य दृष्टिकोणों के लिए, this question और संभावित रूप से स्वीकृत उत्तर में दिए गए कोडप्रोजेक्ट लिंक देखें।

इनपुट स्ट्रिंग विभाजित करने के बाद, आप words से अधिक पुनरावृति और उन है कि अपनी सूची में कुछ भी मेल खाते हैं जगह ले सकता है (swearWords.Contains(word) का उपयोग जांच करने के लिए) या बस का पता लगाने अगर वहाँ सब पर

var anySwearWords = words.Intersect(swearWords).Any(); 
संबंधित मुद्दे