2009-05-18 12 views
13

मैं समानार्थी को संग्रहीत करने के लिए हैश मैप का उपयोग कर थिसॉरस बना रहा हूं।जावा: रेगेक्स पर आधारित हैश मैप कुंजी में खोजें?

मैं नियमित अभिव्यक्ति के आधार पर शब्दों को खोजने की कोशिश कर रहा हूं: विधि को पैरामीटर के रूप में एक स्ट्रिंग लेनी होगी और परिणाम की एक सरणी वापस करनी होगी। यहाँ इस पर मेरा पहला वार है:

public ArrayList<String> searchDefinition(String regex) { 
    ArrayList<String> results = new ArrayList<String>(); 

    Pattern p = Pattern.compile(regex); 

    Set<String> keys = thesaurus.keySet(); 
    Iterator<String> ite = keys.iterator(); 

    while (ite.hasNext()) { 
     String candidate = ite.next(); 
     Matcher m = p.matcher(candidate); 
     System.out.println("Attempting to match: " + candidate + " to " + regex); 
     if (m.matches()) { 
      System.out.println("it matches"); 
      results.add(candidate); 
     } 
    } 

    if (results.isEmpty()) { 
     return null; 
    } 
    else { 
     return results; 
    } 
} 

अब, यह के रूप में मैं उम्मीद होती है (या शायद मैं नियमित अभिव्यक्ति गलत तरीके से उपयोग कर रहा हूँ) काम नहीं करता। अगर मैं hashmap में निम्नलिखित कुंजी:

cat, car, chopper 

तो searchDefinition("c") या searchDefinition("c*") फोन करके मैं null मिलता है।

  1. मैं इस काम को अपेक्षित कैसे कर सकता हूं?
  2. क्या थिसॉरस द्वारा आवश्यक रखने के लिए हैश मैप की तुलना में बेहतर डेटा संरचना है? (जिज्ञासा केवल, इस असाइनमेंट के लिए हमें जावा संग्रह मानचित्र का उपयोग करने के लिए कहा जाता है)।
  3. और कुछ भी मैं ऊपर दिए गए कोड में निर्दोष रूप से कर रहा हूं?

धन्यवाद, दान

संपादित करें: मैं उदाहरण में सुधार किया है। यह सही काम का उपयोग करने पर भी काम नहीं करता है।

+0

क्लिंट का जवाब है। लेकिन ध्यान दें कि कॉलिंग() "c *" के साथ _any_ प्रविष्टि से मेल खाएगी - क्योंकि सभी प्रविष्टियों में 0 या अधिक सी है। अपने regexes से सावधान रहें। –

+0

खासकर जब से आप सीधे पैटर्न कंपाइलर में रेगेक्स पास कर रहे हैं। आप आसानी से PatternSyntaxException प्राप्त कर सकते हैं। – Clint

+0

सवाल नहीं है, लेकिन खाली के लिए शून्य वापस न करें और लूप के लिए बढ़ाए गए उपयोग का उपयोग करें। –

उत्तर

10

आपको केस असंवेदनशीलता Pattern.compile("c",Pattern.CASE_INSENSITIVE) निर्दिष्ट करने की आवश्यकता है। c के साथ एक शब्द खोजने के लिए आपको matcher.find() का उपयोग करने की आवश्यकता है। Matcher.matches() पूरी स्ट्रिंग से मेल खाने का प्रयास करता है।

+1

मुझे मारो (शायद क्योंकि मैंने दस्तावेज़ों से लिंक करने के लिए रोका: पी)। –

+4

पहले पोस्ट करें तो पागल की तरह संपादित करें! – Clint

+0

धन्यवाद! वह चाल है। तो, इसे सीधे प्राप्त करने के लिए: * मुझे ढूंढने के लिए उपयोग करना चाहिए() यदि मैं एक निश्चित रेगेक्स * मिलान() "सभी" शब्द ढूंढना चाहता हूं जो कि कुछ निश्चित शब्द "कुछ" हैं, कुछ भी नहीं है कम, कुछ और नहीं – Dan

2

नियमित अभिव्यक्ति केस संवेदनशील हैं। आप चाहते हैं:

Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); 
+0

क्षमा करें, बुरा उदाहरण। मैंने सवाल संपादित कर लिया है। यह उचित काम का उपयोग करने पर भी काम नहीं करता है। – Dan

2

ऐसा लगता है कि आप अपने regexes को अनुपयुक्त तरीके से उपयोग कर रहे हैं। "सी" केवल एक निचले मामले सी से मेल खाएगा, ऊपरी मामले में नहीं।

यह कहा गया कि, मैं सुझाव दूंगा कि आप पूर्ण टेक्स्ट खोज क्षमताओं वाले एम्बेडेड डेटाबेस का उपयोग करने के लिए देखें।

3

क्या आप नियमित अभिव्यक्ति का उपयोग कर रहे हैं?

Matcher.matches() विधि सच रिटर्न केवल तभी पूरे पूरे इनपुट अनुक्रम (जावाडोक से) एक्सप्रेशन से मेल खाता है, तो आप इस मामले में "c.*" का उपयोग करने की आवश्यकता होगी, मामले insensitively मिलान नहीं "c*" के साथ-साथ।

+0

"सी *" "ग्लोब" वाक्यविन्यास होगा। –

10

लेकिन, हम्म:

(क) क्यों आप एक HashMap का प्रयोग करेंगे, तो आप हमेशा क्रमिक रूप से यह खोज करने के लिए करना चाहते हैं? हैश कुंजी को संसाधित करने के लिए यह बहुत बर्बाद ओवरहेड है और जब आप कभी उनका उपयोग नहीं करते हैं। निश्चित रूप से एक साधारण ArrayList या LinkedList एक बेहतर विचार होगा।

(बी) थिसॉरस के साथ इसका क्या संबंध है? नियमित अभिव्यक्तियों का उपयोग करके आप थिसॉरस क्यों खोजेंगे? अगर मैं समानार्थी शब्द जानना चाहता हूं, तो कहें, "बिल्ली", मुझे लगता है कि मैं "बिल्ली" की खोज करूंगा, न कि "सी। *"।

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

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

मैं अंतर्निहित जावा संग्रह में कोई भी वर्ग नहीं जानता जो ऐसा करता है। सबसे आसान तरीका मैं सोच सकता हूं कि दो सह-समन्वयित हैश तालिकाओं का निर्माण करना है: वह जो टोकन को शब्दों को मानचित्र करता है, और दूसरा जो टोकन को शब्दों की सरणी में मैप करता है। तो तालिका 1 में बड़ा हो सकता है-> 1, बड़ा-> 1, विशाल-> 1, बिल्ली-> 2, बिल्ली का बच्चा-> 2, आदि। फिर तालिका 2 मानचित्र 1 -> [बड़ा, बड़ा, विशाल], 2-> [बिल्ली, बिल्ली का बच्चा], आदि। आप एक टोकन में एक शब्द को मैप करने के लिए पहली तालिका में देखते हैं, और दूसरे शब्दों में शब्दों की सूची में टोकन को मैप करने के लिए। यह बेकार है क्योंकि सभी डेटा अनावश्यक रूप से संग्रहीत किया जाता है, शायद एक बेहतर समाधान है लेकिन मैं इसे अपने सिर के ऊपर से नहीं निकाल रहा हूं। (ठीक है, अगर हम मानते हैं कि हम अनुक्रमिक रूप से शब्दों की पूरी सूची को हर बार खोजना चाहते हैं, लेकिन प्रदर्शन बड़े हो जाएगा क्योंकि प्रदर्शन बड़ा हो गया है।)

0

ऊपर "लेकिन हम्म" के जय का जवाब ,

(मैं एक टिप्पणी जोड़ने के हैं, लेकिन प्रतिनिधि नहीं है।)

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

कारण यह स्पष्ट नहीं है क्योंकि यह एक संग्रह नहीं है। यह दो है। लेकिन यह दो नक्शे नहीं है। यह एक ArrayList नहीं है। क्या गुम है एक सेट है। यह synonyms के सेट करने के लिए एक नक्शा है।

सेट < स्ट्रिंग > आपको समानार्थी की अपनी सूचियां बनाने देगा। आप जितना चाहें उतना कर सकते हैं। समानार्थी के दो सेट एक अच्छा उदाहरण बना देंगे। यह एक सेट है जो एक ऐरेलिस्ट नहीं है क्योंकि आप डुप्लिकेट शब्द नहीं चाहते हैं।

मानचित्र < स्ट्रिंग, सेट < स्ट्रिंग > > आप जल्दी से अपने पर्याय सेट करने के लिए किसी भी शब्द से अपना रास्ता खोजें करने देगा।

अपने सेट बनाएं। फिर नक्शा बनाएं। नक्शा बनाने और एक सेट लेने के लिए एक सहायक विधि लिखें।

addSet (मानचित्र < स्ट्रिंग, सेट < स्ट्रिंग > > नक्शा, सेट < स्ट्रिंग > newSet)

इस विधि सिर्फ newSet लूप और चाबी के रूप में नक्शे और मूल्य के रूप में newSet के संदर्भ में करने के लिए तार जोड़ता है। आप प्रत्येक सेट के लिए एक बार एडसेट को कॉल करेंगे।

अब जब आप डेटा संरचना बना रहे हैं तो हमें सामान ढूंढने में सक्षम होना चाहिए। इसे थोड़ा और मजबूत बनाने के लिए, खोज करने से पहले अपनी खोज कुंजी को साफ़ करना याद रखें। अर्थहीन व्हाइटस्पेस से छुटकारा पाने के लिए ट्रिम() का उपयोग करें। अर्थहीन पूंजीकरण से छुटकारा पाने के लिए toLowerCase() का उपयोग करें। आपको सेट बनाने के पहले (या जबकि) समानार्थी डेटा पर इन दोनों को करना चाहिए था। ऐसा करें और इसके लिए नियमित अभिव्यक्तियों की आवश्यकता कौन है? इस तरह से बहुत तेज और अधिक महत्वपूर्ण रूप से सुरक्षित है। नियमित अभिव्यक्ति बहुत शक्तिशाली होती है लेकिन गलत होने पर डीबग करने के लिए एक दुःस्वप्न हो सकता है। उनका उपयोग न करें क्योंकि आपको लगता है कि वे शांत हैं।

+0

रेगेक्स का उपयोग करने का बिंदु इसलिए नहीं है क्योंकि वे "शांत" हैं। रेगेक्स का उपयोग करने का बिंदु इसलिए है क्योंकि उन्हें समझना मुश्किल होता है, इसलिए यदि आप इसे काम कर सकते हैं जो साबित करता है कि आप उन लोगों की तुलना में अधिक स्मार्ट हैं जो बाद में अपना कोड पढ़ते हैं और इसे समझ नहीं सकते हैं। :-) – Jay

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