2015-07-02 54 views
7

के साथ शब्द गणना मैं जावा 8 में एक शब्द गणना कार्यक्रम को लागू करने की कोशिश कर रहा हूं लेकिन मैं इसे काम करने में असमर्थ हूं। विधि को पैरामीटर के रूप में एक स्ट्रिंग लेनी चाहिए और Map<String,Integer> देता है।जावा 8

जब मैं इसे पुराने जावा तरीके से कर रहा हूं, तो कुछ भी ठीक काम करता है। लेकिन जब मैं जावा 8 में ऐसा करने की कोशिश कर रहा हूं, तो यह एक नक्शा देता है जहां कुंजी सही घटनाओं के साथ खाली होती है।

public Map<String, Integer> count(String input){ 
     Map<String, Integer> wordcount = new HashMap<>(); 
     Pattern compile = Pattern.compile("(\\w+)"); 
     Matcher matcher = compile.matcher(input); 

     while(matcher.find()){ 
      String word = matcher.group().toLowerCase(); 
      if(wordcount.containsKey(word)){ 
       Integer count = wordcount.get(word); 
       wordcount.put(word, ++count); 
      } else { 
       wordcount.put(word.toLowerCase(), 1); 
      } 
     } 
     return wordcount; 
} 

मुख्य कार्यक्रम:

public static void main(String[] args) { 
     WordCount wordCount = new WordCount(); 
     Map<String, Integer> phrase = wordCount.countJava8("one fish two fish red fish blue fish"); 
     Map<String, Integer> count = wordCount.count("one fish two fish red fish blue fish"); 

     System.out.println(phrase); 
     System.out.println(); 
     System.out.println(count); 
    } 

public Map<String, Integer> countJava8(String input){ 
     return Pattern.compile("(\\w+)").splitAsStream(input).collect(Collectors.groupingBy(e -> e.toLowerCase(), Collectors.reducing(0, e -> 1, Integer::sum))); 
    } 

यहाँ कोड मैं एक सामान्य स्थिति में प्रयोग करेंगे है:

यहाँ एक जावा 8 शैली में मेरी कोड है

जब मैं इस प्रोग्राम को चलाता हूं, मेरे पास आउटपुट है:

{ =7, =1} 
{red=1, blue=1, one=1, fish=4, two=1} 

मैंने सोचा कि विधि splitAsStreamStream के रूप में regex में मिलान तत्वों को स्ट्रीम करेगा। मैं इसे कैसे ठीक कर सकता हूं?

+0

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

+0

'wordCount.Phrase() 'क्या है? –

+3

समस्या यह है कि आप '\ w' द्वारा 'विभाजित' करते हैं, इसलिए आप मूल रूप से सबकुछ प्राप्त करते हैं जो _not_ शब्द है। –

उत्तर

8

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

इसके बजाय, आप \w के बजाय \W का उपयोग करके गैर-शब्दों से विभाजित हो सकते हैं। साथ ही, टिप्पणियों में उल्लेख के अनुसार, आप इसे थोड़ा लाम्बाडा और Collectors.summingInt के बजाय String::toLowerCase का उपयोग करके अधिक पठनीय बना सकते हैं।

public static Map<String, Integer> countJava8(String input) { 
    return Pattern.compile("\\W+") 
        .splitAsStream(input) 
        .collect(Collectors.groupingBy(String::toLowerCase, 
               Collectors.summingInt(s -> 1))); 
} 

लेकिन IMHO यह अभी भी न केवल 'उलटी "देखने की वजह से समझने के लिए, बहुत मुश्किल है, और यह भी अन्य, अधिक जटिल पैटर्न के सामान्यीकरण करने के लिए मुश्किल है। निजी तौर पर, मैं बस "पुराने स्कूल" समाधान के साथ जाऊंगा, शायद इसे getOrDefault का उपयोग करके थोड़ा अधिक कॉम्पैक्ट बना देगा।

public static Map<String, Integer> countOldschool(String input) { 
    Map<String, Integer> wordcount = new HashMap<>(); 
    Matcher matcher = Pattern.compile("\\w+").matcher(input); 
    while (matcher.find()) { 
     String word = matcher.group().toLowerCase(); 
     wordcount.put(word, wordcount.getOrDefault(word, 0) + 1); 
    } 
    return wordcount; 
} 

परिणाम दोनों मामलों में समान प्रतीत होता है।

+0

युप के बजाय लंबे समय तक लौटाता है, पैटर्न के लिए जावाडोक कहता है कि splitAsStream बनाता है पैटर्न _around_ पैटर्न के मैचों। –

+3

मेरे लिए, 'collect.counting() 'संग्राहक.summingInt (s -> 1)' से क्लीनर दिखता है। बेशक, आपको 'मैप <स्ट्रिंग' के परिणाम प्रकार के साथ रहना होगा, लंबा> 'फिर ... – Holger

+3

वैसे, जावा 9 के साथ, आप [मैचों पर स्ट्रीम] कर सकते हैं (http://download.java.net/jdk9/docs/api/java/util/regex/Matcher.html#results- -), इसलिए आपको पैटर्न को उलटा करने की आवश्यकता नहीं है, हालांकि परिणामस्वरूप कोड थोड़ा बड़ा है: 'Pattern.compile (" \\ w + ") वापस लौटें। एचर (इनपुट) .results() .collect (collect.groupingBy (r-> r.group()। toLowerCase(), संग्राहक.counting())); – Holger

0

इसे आजमाएं। एसडी, Occurrency: 1

स्ट्रिंग: जाओ, Occurrency: 4

स्ट्रिंग: ओग, Occurrency:

String in = "go go go go og sd"; 
    Map<String, Integer> map = new HashMap<String, Integer>(); 
    //Replace all punctuation with space 
    String[] s = in.replaceAll("\\p{Punct}", " ").split("\\s+"); 
    for(int i = 0; i < s.length; i++) 
    { 
     map.put(s[i], i); 
    } 
    Set<String> st = new HashSet<String>(map.keySet()); 
    for(int k = 0; k < s.length; k++) 
    { 
    int i = 0; 
    Pattern p = Pattern.compile(s[k]); 
    Matcher m = p.matcher(in); 
    while (m.find()) { 
     i++; 
    } 
    map.put(s[k], i); 
    } 
    for(String strin : st) 
    { 
     System.out.println("String: " + strin.toString() + " - Occurrency: " + map.get(strin.toString())); 
    } 
    System.out.println("Word: " + s.length); 

यह आउटपुट

स्ट्रिंग है 1

पद : 6

+0

यह विराम चिह्न को कैसे संभालता है? –

+0

आप विराम चिह्न के साथ तारों को प्रबंधित करना चाहते हैं? मैं विराम चिह्न पहचान के साथ कोड संपादित करें –