2009-06-29 12 views
7

सी # में नियमित अभिव्यक्तियों का उपयोग करना, क्या स्ट्रिंग में डुप्लिकेट शब्दों या प्रतीकों को खोजने और निकालने का कोई तरीका है जिसमें विभिन्न शब्द और प्रतीकों हैं?डुप्लिकेट शब्दों को खोजने और निकालने के लिए नियमित अभिव्यक्ति

पूर्व।

शब्दों का प्रारंभिक स्ट्रिंग:

"।। मैं पर्यावरण की तरह वातावरण अच्छा है"

वांछित स्ट्रिंग:

"। मैं पर्यावरण की तरह अच्छा है"

डुप्लिकेट हटाया: "", "पर्यावरण", "।"

+4

इसके लिए क्या उद्देश्य है? –

उत्तर

12

के रूप में दूसरों के द्वारा कहा, तुम एक regex से अधिक की आवश्यकता शब्दों का ट्रैक रखने के:

var words = new HashSet<string>(); 
string text = "I like the environment. The environment is good."; 
text = Regex.Replace(text, "\\w+", m => 
        words.Add(m.Value.ToUpperInvariant()) 
         ? m.Value 
         : String.Empty); 
+0

ToUpperInvariant ToLower को पसंद किया जाता है, और यदि आप lambdas है, तो आप HashSet जो बदलता है शब्दकोश <स्ट्रिंग, स्ट्रिंग> जहां कुंजी == मान। अन्यथा, +1। – user7116

+0

धन्यवाद। ToUpperInvariant का उपयोग करने से कोई प्रदर्शन लाभ है या सिर्फ सम्मेलन है? –

+0

हैशसेट कन्स्ट्रक्टर एक वैकल्पिक IEqualityComparer लेता है, और इसकी ऐड विधि एक बुलियन दर्शाती है कि यह सेट सेट में मौजूद है या नहीं। तो आप अपने हैंशसेट को "var words = new हैशसेट (स्ट्रिंगकॉम्पियर.ऑर्डिनल इग्नोरकेस) के साथ तुरंत चालू कर सकते हैं;" और उसके बाद अपने प्रतिनिधि को एक लाइनर में कम करें: "वापसी शब्द। जोड़ें (एम। वाल्यू)? एम। वैल्यू: स्ट्रिंग। लक्षण;" – LukeH

4

ठीक है, जेफ ने मुझे दिखाया है कि यह अभिव्यक्ति बैक्रेरेंस के जादू का उपयोग कैसे करें और यह करने के लिए वैश्विक संशोधक, इसलिए मेरा मूल उत्तर निष्क्रिय है। आपको जेफ के जवाब के लिए वोट देना चाहिए। हालांकि, भावी पीढ़ी के लिए मैं ध्यान दें जाएगा इस एक में एक मुश्किल थोड़ा regex इंजन संवेदनशीलता मुद्दा यह है कि, और यदि आप पर्ल के स्वाद का regex उपयोग कर रहे थे, तो आप ऐसा करने के लिए की आवश्यकता होगी:

\b(\S+)\b(?=.*\b\1\b.*) 
जेफ के जवाब के बजाय

, क्योंकि सी # रेगेक्स प्रभावी रूप से \b\1 पर प्रभावी ढंग से कैप्चर करेगा लेकिन पीसीआरई नहीं करेगा।
http://msdn.microsoft.com/en-us/library/thwdfzxy(VS.71).aspx

यह एक regex कि दोगुनी शब्द मिलेगा:

+1

हम सब इस सड़क से नीचे आ गए हैं ... "कुछ लोग, जब किसी समस्या का सामना करते हैं, तो सोचें 'मुझे पता है, मैं नियमित अभिव्यक्तियों का उपयोग करूंगा।' अब उन्हें दो समस्याएं हैं। " –

+0

लेकिन क्या आज कोई रेगेक्स इंजन है जो आजकल किसी भी प्रकार की स्थिति का समर्थन नहीं करता है? बैक्रेरेंस के साथ यह एक बहुत ही सरल कार्य है। असल में, मुझे लगता है कि इस तरह कुछ ऐसा ऊंट पुस्तक (प्रोग्रामिंग पर्ल) में बैकरेरेंस प्रदर्शित करने के लिए किया जाता है। – arnsholt

+0

हाँ, ठीक है, नीचे मेरा regex देखें जो –

2

backreferences पर एक नज़र डालें। लेकिन यह प्रति मैच केवल एक शब्द से मेल खाता है। तो आपको इसे एक से अधिक बार उपयोग करना होगा।

new Regex(@"(.*)\b(\w+)\b(.*)(\2)(.*)", RegexOptions.IgnoreCase); 

बेशक यह सबसे अच्छा समाधान (अन्य उत्तर है, जो सब पर एक regex का उपयोग नहीं करने का प्रस्ताव देखें) नहीं है। लेकिन आपने रेगेक्स के लिए कहा - यहां एक है। शायद सिर्फ विचार आपको मदद करता है ...

0

रेगेक्स सब कुछ के लिए उपयुक्त नहीं है। आपकी समस्या की तरह कुछ उस श्रेणी में पड़ता है। मैं आपको इसके बजाय एक पार्सर का उपयोग करने की सलाह दूंगा।

-2

जैसा कि अन्य ने बताया है, यह बैक्रेरेंस के साथ काम करने योग्य है। .NET में बैक्रेरेंस का उपयोग करने के तरीके के बारे में विवरण के लिए http://msdn.microsoft.com/nb-no/library/thwdfzxy(en-us).aspx देखें।

आपका विशेष समस्या विराम चिह्न निकालें साथ ही यह थोड़ा और अधिक जटिल बना देता है, लेकिन मैं इन पंक्तियों के साथ कोड लगता है (सफेद स्थान है कि regex में महत्वपूर्ण नहीं है) करना चाहिए चाल:

(\b\w+(?:\s+\w+)*)\s+\1 

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

+0

वास्तव में काम नहीं करता है ... –

-1

आप इस समस्या के लिए रेगुलर एक्सप्रेशन का उपयोग करने में सक्षम नहीं होगा, क्योंकि regex केवल नियमित भाषाओं से मेल खाता है।जिस पैटर्न को आप मिलान करने का प्रयास कर रहे हैं वह संदर्भ-संवेदनशील है, और इसलिए "नियमित" नहीं है।

सौभाग्य से, यह काफी आसान एक पार्सर लिखने के लिए है। प्रति एरिक स्टेंडहल के कोड पर एक नज़र डालें।

1

रेगुलर एक्सप्रेशन इस समस्या को हल करने के लिए "उपकरण" के एक गरीब विकल्प होगा। शायद निम्नलिखित काम कर सकता था:

HashSet<string> corpus = new HashSet<string>(); 
char[] split = new char[] { ' ', '\t', '\r', '\n', '.', ';', ',', ':', ... }; 

foreach (string line in inputLines) 
{ 
    string[] parts = line.Split(split, StringSplitOptions.RemoveEmptyEntries); 
    foreach (string part in parts) 
    { 
     corpus.Add(part.ToUpperInvariant()); 
    } 
} 

// 'corpus' now contains all of the unique tokens 

संपादित करें: यह मेरे लिए एक बड़ा धारणा है कि आप खोज की तरह विश्लेषण के कुछ प्रकार के लिए "lexing" कर रहे हैं बना रही है।

10

यह बहुत

 
apple apple orange 
orange red bluegreen orange green blue 
piratesninjas cowboys ninjas pirates 
+0

क्या यह मामला असंवेदनशील मैच करता है? – Robert

+0

ऐसा लगता है कि वह शब्द के दूसरे उदाहरण से मेल खाना चाहता है, पहले नहीं। – Robert

+0

इसे 'समुद्री डाकू निंजा काउबॉय निंजा समुद्री डाकू डलासकोबॉय' पर भी आज़माएं। – chaos

0

Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems.

की तरह मुझे

(\b\S+\b)(?=.*\1) 

मैचों के लिए काम करने के लिए देखें लगता When not to use Regex in C# (or Java, C++ etc)

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

संबंधित मुद्दे