2010-07-09 6 views
7

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

String test = "This is a test string and I have some stopwords in here"; 

है और मैं

psudocode

array = a,and,the,them,they,I 

तो जवाब होगा कितनी बार मेरी स्ट्रिंग के खिलाफ मैच के नीचे सरणी में शब्द देखना चाहते हैं, "3"

सिर्फ उत्सुक है कि जावा में ऐसा करने का सबसे प्रभावी तरीका क्या है?

+0

दिलचस्प सवाल, मुझे देखने दो कि क्या मैं बेवकूफ एल्गोरिदम – quantumSoup

+0

से बेहतर कुछ के साथ आ सकता हूं दोहराने के बारे में क्या? नीचे दिए गए उत्तर सेट्स में डेटा पढ़ते हैं, जो "ए और" के लिए 3 स्कोर करेगा लेकिन "ए ए" के लिए केवल 1 होगा।क्या वांछित व्यवहार है, या दोनों रिपोर्ट 3 चाहिए? – Chadwick

उत्तर

5

मैं शायद इनपुट में शब्दों को हैशसेट में संग्रहीत करता हूं और फिर सरणी पर फिर से चलाता हूं और देखता हूं कि सरणी में प्रत्येक शब्द है। सेट में शामिल है।

यहां यह कोड में है ... इनपुट "Around the world in 80 days" है।

import java.io.File; 
import java.io.FileNotFoundException; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Scanner; 
import java.util.Set; 

public class Main 
{ 
    public static void main(final String[] argv) 
     throws FileNotFoundException 
    { 
     final File  file; 
     final String[] wordsToFind; 

     file  = new File(argv[0]); 
     wordsToFind = getWordsToFind(file); 
     a(file, wordsToFind); 
     b(file, wordsToFind); 
     c(file, wordsToFind); 
     d(file, wordsToFind); 
    } 

    // this just reads the file into the disk cache 
    private static String[] getWordsToFind(final File file) 
     throws FileNotFoundException 
    { 
     final Scanner  scanner; 
     final Set<String> words; 

     scanner = new Scanner(file); 
     words = new HashSet<String>(); 

     while(scanner.hasNext()) 
     { 
      final String word; 

      word = scanner.next(); 
      words.add(word); 
     } 

     return (words.toArray(new String[words.size()])); 
    } 

    // bad way, read intpo a list and then iterate over the list until you find a match 
    private static void a(final File  file, 
          final String[] wordsToFind) 
     throws FileNotFoundException 
    { 
     final long start; 
     final long end; 
     final long total; 
     final Scanner  scanner; 
     final List<String> words; 
     int    matches; 

     scanner = new Scanner(file); 
     words = new ArrayList<String>(); 

     while(scanner.hasNext()) 
     { 
      final String word; 

      word = scanner.next(); 
      words.add(word); 
     } 

     start = System.nanoTime(); 

     { 
      matches = 0; 

      for(final String wordToFind : wordsToFind) 
      { 
       for(final String word : words) 
       { 
        if(word.equals(wordToFind)) 
        { 
         matches++; 
         break; 
        } 
       } 
      } 

      System.out.println(matches); 
     } 

     end = System.nanoTime(); 
     total = end - start; 
     System.out.println("a: " + total); 
    } 

    // slightly better way, read intpo a list and then iterate over the set (which reduces the number of things you progbably 
    // have to read until you find a match), until you find a match 
    private static void b(final File  file, 
          final String[] wordsToFind) 
     throws FileNotFoundException 
    { 
     final long start; 
     final long end; 
     final long total; 
     final Scanner  scanner; 
     final Set<String> words; 
     int    matches; 

     scanner = new Scanner(file); 
     words = new HashSet<String>(); 

     while(scanner.hasNext()) 
     { 
      final String word; 

      word = scanner.next(); 
      words.add(word); 
     } 

     start = System.nanoTime(); 

     { 
      matches = 0; 

      for(final String wordToFind : wordsToFind) 
      { 
       for(final String word : words) 
       { 
        if(word.equals(wordToFind)) 
        { 
         matches++; 
         break; 
        } 
       } 
      } 

      System.out.println(matches); 
     } 

     end = System.nanoTime(); 
     total = end - start; 
     System.out.println("b: " + total); 
    } 

    // my way 
    private static void c(final File  file, 
          final String[] wordsToFind) 
     throws FileNotFoundException 
    { 
     final long start; 
     final long end; 
     final long total; 
     final Scanner  scanner; 
     final Set<String> words; 
     int    matches; 

     scanner = new Scanner(file); 
     words = new HashSet<String>(); 

     while(scanner.hasNext()) 
     { 
      final String word; 

      word = scanner.next(); 
      words.add(word); 
     } 

     start = System.nanoTime(); 

     { 
      matches = 0; 

      for(final String wordToFind : wordsToFind) 
      { 
       if(words.contains(wordToFind)) 
       { 
        matches++; 
       } 
      } 

      System.out.println(matches); 
     } 

     end = System.nanoTime(); 
     total = end - start; 
     System.out.println("c: " + total); 
    } 

    // Nikita Rybak way 
    private static void d(final File  file, 
          final String[] wordsToFind) 
     throws FileNotFoundException 
    { 
     final long start; 
     final long end; 
     final long total; 
     final Scanner  scanner; 
     final Set<String> words; 
     int    matches; 

     scanner = new Scanner(file); 
     words = new HashSet<String>(); 

     while(scanner.hasNext()) 
     { 
      final String word; 

      word = scanner.next(); 
      words.add(word); 
     } 

     start = System.nanoTime(); 

     { 
      words.retainAll(new HashSet<String>(Arrays.asList(wordsToFind))); 
      matches = words.size(); 
      System.out.println(matches); 
     } 

     end = System.nanoTime(); 
     total = end - start; 
     System.out.println("d: " + total); 
    } 
} 

परिणाम (कुछ रन के बाद, प्रत्येक रन काफी समान हालांकि है):

12596 
a: 2440699000 
12596 
b: 2531635000 
12596 
c: 4507000 
12596 
d: 5597000 

आप (getWordsToFind में शब्दों में से प्रत्येक के लिए "XXX" जोड़ें, ताकि द्वारा इसे संशोधित यदि कोई शब्द पाए जाते हैं) आपको मिलेगा:

0 
a: 7415291000 
0 
b: 4688973000 
0 
c: 2849000 
0 
d: 7981000 

और, संपूर्णता के लिए, मैं इसे करने की कोशिश की तो बस शब्द "मैं" के लिए खोज, और परिणाम हैं:

1 
a: 235000 
1 
b: 351000 
1 
c: 75000 
1 
d: 10725000 
5

ऐसा कुछ? 'सबसे कुशल' के बारे में निश्चित नहीं है, लेकिन काफी सरल है।

Set<String> s1 = new HashSet<String>(Arrays.asList("This is a test string and I have some stopwords in here".split("\\s"))); 
Set<String> s2 = new HashSet<String>(Arrays.asList("a", "and", "the", "them", "they", "I")); 
s1.retainAll(s2); 
System.out.println(s1.size()); 

शब्दों के दो सेटों का बस छेड़छाड़।

+0

सेट छेड़छाड़ निश्चित रूप से – Eric

3

करने के लिए सबसे कारगर बात प्रकार दोनों 'परीक्षण' और 'सरणी' और फिर दोनों से अधिक पुनरावृति है: n.log (एन) + n

परीक्षण -> [ 'एक', 'और', 'है', 'यहां', में, है, ..., 'यह'] सरणी -> ['ए', 'और', 'द', 'उन्हें', 'वे', 'मैं']

सरणी परीक्षण से मेल खाता है 'एक' 'एक' 1 'एक' 'और' 1 'और' 'और' 2 'और' है 'और' 2 '' 'यहाँ' 2 '' 'इन' 2 'द' 'है' 2 ...

+0

@ एरिकुल जाने का सही तरीका है, क्योंकि दोनों ऑर्डर किए गए सरणी एक साथ घुमाए जाते हैं। इस एल्गोरिदम के साथ एकमात्र समस्या यह है कि यह प्रत्यारोपण के लिए इतना छोटा नहीं है :) –

+0

+1, लेकिन यह सबसे प्रभावी तरीका नहीं है। यहां जबकि हमारे पास ओ (एन लॉग (एन)) है, हैश ऑपरेशंस निरंतर समय लेते हैं और इस प्रकार लक्ष्य ओ (एन) में हासिल किया जा सकता है। –

+0

@ एरकुले ऐसा नहीं है। आपके पास दो अलग-अलग इंडेक्स (i और j) हैं और सबसे कम मूल्य वाले एक को बढ़ाएं: _if (a [i] <= b [j]) {++ i} else {++ j}; _ –

0

निकिता के उत्तर पर एक मामूली बदलाव (निकिता के लिए ऊपर 1)। यदि आप एस 1 के लिए एक सूची का उपयोग करते हैं, तो आपको घटनाओं की संख्या मिलती है (यदि वाक्य में एक शब्द कई बार प्रकट होता है)।

List<String> s1 = new ArrayList<String>(Arrays.asList("This is a test string and I have some stopwords in here".split("\\s"))); 
Set<String> s2 = new HashSet<String>(Arrays.asList("a", "and", "the", "them", "they", "I")); 
s1.retainAll(s2); 
System.out.println(s1.size()); 
0

दुकान hashtable में अपने तार, तो पाठ के ऊपर इटरेटर ((स्ट्रिंग और पूर्णांक) की HashMap) और hashtable में मिलान शब्द के लिए पूर्णांक मान बढ़ा सकते हैं। फिर हैशटेबल पर iterator और सभी पूर्णांक मान योग।

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

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