2010-07-09 27 views
7

ı bir dizeKibrit sayımı bulmak için en etkili yol bir dizi kelime karşı bir dizi var?

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

var ve

psudocode

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

yüzden cevap olacağını kaç kez maç altına dizideki sözler benim dize karşı görmek istiyorum diyelim "3"

Sadece java yapmak için en etkili yolu ne olduğunu merak ediyor?

+0

İlginç bir soru, naif algoritmadan daha iyi bir şey bulabilirmiyim bakalım – quantumSoup

+0

Tekrarlar hakkında ne dersiniz? Cevaplar, verileri "a ve" için 3, "a a a" için ise 1 olacak şekilde ayarlar.İstenen davranış bu mu yoksa her ikisi de rapor 3? – Chadwick

cevap

5

Muhtemelen girdilerdeki sözcükleri bir HashSet'e depolarım ve sonra dizinin üzerine yineleyin ve dizideki her sözcüğün kümede .contains olup olmadığını görün.

Burada kod var ... giriş "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); 
    } 
} 

sonuçları (birkaç koşular sonrasında, her çalışma olsa hemen hemen aynıdır):

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

bunu (getWordsToFind kelimelerin her birine "XXX" ekleyerek değiştirirseniz hayır kelime Alacağınız) bulunur:

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

ve şeyiyle ben sadece kelime "Ben" araması denedim ve sonuçlar şunlardır:

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

Böyle bir şey mi var? 'En verimli' hakkında emin değilim, ama yeterince basit.

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()); 

Sadece iki sözcük kümesinin kesişim noktası.

+0

Kesişen kümeler kesinlikle – Eric

3

yapmak için en etkili olan sıralama her iki 'test' ve 'dizi' ve daha sonra her iki yineleme olup: n.log (n) + n

testi -> [ 'a', 've', 'have', 'here', in, ..., 'This'] array -> ['a', 've', 'the', 'them', 'onlar', 'Ben']

dizi testi 'bir 'bir' 1 , 'a' ve' 1 've' 've' 2 'eşleşir ve 2 ' '' buraya 2 ' 'sahip''' '2 ' içinde '2'dir' 2 ...

+0

@Aircule gitmek için doğru yoldur, çünkü her iki sıralı dizi eşzamanlı olarak katlanır. Bu algoritma ile ilgili tek sorun, bu kadar basit değil :) –

+0

+ 1, ama en etkili yol değil. Burada O (n log (n)) var, hash işlemleri sabit zaman alıyor ve bu nedenle O (n) 'de hedefe ulaşılabiliyor. –

+0

@Aircule bunun gibi değil. iki farklı indeksin (i ve j) var ve en küçük değeri olanı artırın: _if (a [i] <= b [j]) {++ i} else {++ j}; _ –

0

Nikita'nın yanıtında küçük bir varyasyon (Nikita için 1'e kadar). S1 için bir Liste kullanırsanız, olayların sayısını (bir sözcüğün cümlede birden çok kez görünmesi durumunda) alırsınız. HashTable

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

mağaza Dizeleriniz metnin üzerine, daha sonra yineleyici ((String ve Integer) ait HashMap) ve hashtable'a eşleşen sözcük için tamsayı değeri artar. sonra yineleyici hashtable ve tüm tamsayı değerleri toplar.