2011-01-22 38 views
6

phép nói rằng tôi có danh sách các chữ:dây Loại bỏ từ một chuỗi trong java

String[] stopWords = new String[]{"i","a","and","about","an","are","as","at","be","by","com","for","from","how","in","is","it","not","of","on","or","that","the","this","to","was","what","when","where","who","will","with","the","www"}; 

Thần I có văn bản

String text = "I would like to do a nice novel about nature AND people" 

Có phương pháp phù hợp với từ dừng và loại bỏ chúng trong khi bỏ qua trường hợp ; như này ở đâu đó ngoài kia ?:

String noStopWordsText = remove(text, stopWords); 

Kết quả:

" would like do nice novel nature people" 

Nếu bạn biết về regex mà wold công việc tuyệt vời nhưng tôi thực sự muốn một cái gì đó giống như giải pháp commons đó là hơn chút hiệu suất theo định hướng.

BTW, ngay bây giờ tôi đang sử dụng phương pháp này commons mà thiếu thích hợp xử lý trường hợp nhạy cảm:

private static final String[] stopWords = new String[]{"i", "a", "and", "about", "an", "are", "as", "at", "be", "by", "com", "for", "from", "how", "in", "is", "it", "not", "of", "on", "or", "that", "the", "this", "to", "was", "what", "when", "where", "who", "will", "with", "the", "www", "I", "A", "AND", "ABOUT", "AN", "ARE", "AS", "AT", "BE", "BY", "COM", "FOR", "FROM", "HOW", "IN", "IS", "IT", "NOT", "OF", "ON", "OR", "THAT", "THE", "THIS", "TO", "WAS", "WHAT", "WHEN", "WHERE", "WHO", "WILL", "WITH", "THE", "WWW"}; 
private static final String[] blanksForStopWords = new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}; 

noStopWordsText = StringUtils.replaceEach(text, stopWords, blanksForStopWords);  
+0

Bạn có dấu câu trong chuỗi của mình không? – Gabe

+0

Bạn có một số con số khó mà chỉ đến một giải pháp regexp không được thực hiện đủ, hoặc là chỉ cần tối ưu hóa sớm? Ý tôi là, nó chắc chắn không phải là giải pháp hiệu suất nhất _the_, nhưng trừ khi đây là tất cả những gì bạn làm và bạn cần thực hiện nó 10K lần trong một giây, tôi sẽ đặt cược nó không phải là một vấn đề. – Theo

Trả lời

4

Đây là giải pháp không sử dụng cụm từ thông dụng. Tôi nghĩ rằng nó thấp hơn câu trả lời khác của tôi vì nó dài hơn và ít rõ ràng hơn, nhưng nếu hiệu suất thực sự quan trọng thì đây là O (n) trong đó n là độ dài của văn bản.

Set<String> stopWords = new HashSet<String>(); 
stopWords.add("a"); 
stopWords.add("and"); 
// and so on ... 

String sampleText = "I would like to do a nice novel about nature AND people"; 
StringBuffer clean = new StringBuffer(); 
int index = 0; 

while (index < sampleText.length) { 
    // the only word delimiter supported is space, if you want other 
    // delimiters you have to do a series of indexOf calls and see which 
    // one gives the smallest index, or use regex 
    int nextIndex = sampleText.indexOf(" ", index); 
    if (nextIndex == -1) { 
    nextIndex = sampleText.length - 1; 
    } 
    String word = sampleText.substring(index, nextIndex); 
    if (!stopWords.contains(word.toLowerCase())) { 
    clean.append(word); 
    if (nextIndex < sampleText.length) { 
     // this adds the word delimiter, e.g. the following space 
     clean.append(sampleText.substring(nextIndex, nextIndex + 1)); 
    } 
    } 
    index = nextIndex + 1; 
} 

System.out.println("Stop words removed: " + clean.toString()); 
+0

Rất đúng, tôi đã thay đổi 'break' thành' nextIndex = sampleText.length', nó sẽ giải quyết điều đó. – Theo

+0

Rất tiếc, đó thực sự là những gì tôi đã thử nghiệm, nhưng tôi đã cẩu thả khi tôi thay đổi mã. Cảm ơn bạn đã chỉ ra điều đó. – Theo

5

Bạn có thể tạo một biểu thức reg để phù hợp với tất cả các điểm dừng chân lời [ví dụ a, lưu ý không gian ở đây] và kết thúc với

str.replaceAll(regexpression,""); 

HOẶC

String[] stopWords = new String[]{" i ", " a ", " and ", " about ", " an ", " are ", " as ", " at ", " be ", " by ", " com ", " for ", " from ", " how ", " in ", " is ", " it ", " not ", " of ", " on ", " or ", " that ", " the ", " this ", " to ", " was ", " what ", " when ", " where ", " who ", " will ", " with ", " the ", " www "}; 
     String text = " I would like to do a nice novel about nature AND people "; 

     for (String stopword : stopWords) { 
      text = text.replaceAll("(?i)"+stopword, " "); 
     } 
     System.out.println(text); 

đầu ra:

would like do nice novel nature people 

Có thể có cách tốt hơn.

+0

1) Không xử lý yêu cầu rằng phương pháp phải phân biệt chữ hoa chữ thường. 2) không loại bỏ dừng _words_ - nó sẽ loại bỏ "không" trong "tiểu thuyết". – Theo

+0

@Theo kiểm tra cập nhật –

+0

Thủ thuật thông minh, không biết điều đó là có thể. Những lời chỉ trích duy nhất tôi có là 'replaceAll' thực sự không hiệu quả, nó biên dịch một mẫu regexp một lần, vì vậy sử dụng nó trong một vòng lặp không phải là tuyệt vời. – Theo

16

Tạo một biểu thức chính quy với các từ dừng của bạn, làm cho nó phân biệt dạng chữ, và sau đó sử dụng phương pháp của khớp replaceAll để thay thế tất cả các trận đấu với một chuỗi rỗng

import java.util.regex.*; 

Pattern stopWords = Pattern.compile("\\b(?:i|a|and|about|an|are|...)\\b\\s*", Pattern.CASE_INSENSITIVE); 
Matcher matcher = stopWords.matcher("I would like to do a nice novel about nature AND people"); 
String clean = matcher.replaceAll(""); 

các ... trong mô hình chỉ là tôi lười biếng , tiếp tục danh sách các từ dừng.

Phương pháp khác là lặp qua tất cả các từ dừng và sử dụng phương thức replaceAll của String. Vấn đề với cách tiếp cận đó là replaceAll sẽ biên dịch một biểu thức chính quy mới cho mỗi cuộc gọi, vì vậy nó không phải là rất hiệu quả để sử dụng trong các vòng lặp. Ngoài ra, bạn không thể chuyển cờ làm cho cụm từ biểu thức chính quy không nhạy cảm khi bạn sử dụng replaceAll của String.

Chỉnh sửa: Tôi đã thêm \b xung quanh mẫu để làm cho nó chỉ khớp toàn bộ từ. Tôi cũng đã thêm \s* để biến nó thành bất kỳ khoảng trống nào sau đó, điều đó có thể không cần thiết.

+0

[mã sẽ hoạt động?] (Http://ideone.com/F7m9f) –

+0

Có, nó nên. Tôi đã có một lỗi trong regexp, \ b cần phải được \\ b trong Java, tôi quên điều đó. Nhưng bây giờ nó sẽ hoạt động. – Theo

+0

Ok. muốn +1 nhưng phiếu bầu của tôi đã bị khóa. –

1

Tách text trên khoảng trắng. Sau đó, lặp qua mảng đó và tiếp tục thêm vào một số StringBuilder chỉ khi nó không phải là một trong những từ dừng.

Các vấn đề liên quan