2013-05-24 35 views
18

Cách tách văn bản thành các từ?Làm cách nào để tách văn bản thành các từ?

Ví dụ văn bản:

'Ồ, bạn không thể giúp đỡ đó,' nói Cát: 'chúng ta đều điên đây. Tôi đang bực. Anh điên rồi.

Những lời trong dòng đó là:

  1. Oh
  2. bạn
  3. không thể
  4. giúp đỡ
  5. rằng
  6. nói
  7. các
  8. Cát
  9. chúng tôi
  10. tất cả
  11. điên
  12. đây
  13. Tôi
  14. điên
  15. Bạn
  16. điên
+4

Lời khuyên của tôi: bắt đầu bằng cách xác định ngữ pháp từ vựng rõ ràng và sau đó viết lexer cho ngữ pháp tạo ra một chuỗi mã thông báo. Sau đó, từ chối các thẻ không được lexed vào sản xuất "từ". Đây không phải là một công việc cho các biểu thức thông thường. –

+0

Tôi thực sự thích phản ứng của Eric. Tôi biết tôi đến muộn một chút, nhưng đó là cách tốt nhất để đi. –

+0

Tôi đã thu thập tất cả dấu phân cách ** ở trên và tôi đã tìm thấy nội dung nào đó như kết quả này.Split ({"'", "", ",",, ":" ",". ",".' "} , StringSplitOptions.RemoveEmptyEntries); –

Trả lời

31

Tách văn bản trên khoảng trắng, sau đó cắt dấu chấm câu.

var text = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'"; 
var punctuation = text.Where(Char.IsPunctuation).Distinct().ToArray(); 
var words = text.Split().Select(x => x.Trim(punctuation)); 

Đồng ý chính xác với ví dụ.

21

Thứ nhất, Hủy bỏ tất cả characeters đặc biệt:

var fixedInput = Regex.Replace(input, "[^a-zA-Z0-9% ._]", string.Empty); 
// This regex doesn't support apostrophe so the extension method is better 

Sau đó chia nó:

var splitted = fixedInput.Split(' '); 

Đối với một C giải pháp # đơn giản để loại bỏ ký tự đặc biệt (mà bạn có thể dễ dàng thay đổi), thêm phương pháp mở rộng này (tôi đã thêm một sự hỗ trợ cho một dấu nháy đơn):

public static string RemoveSpecialCharacters(this string str) { 
    StringBuilder sb = new StringBuilder(); 
    foreach (char c in str) { 
     if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '\'') { 
     sb.Append(c); 
     } 
    } 
    return sb.ToString(); 
} 

Sau đó, sử dụng nó như vậy:

var words = input.RemoveSpecialCharacters().Split(' '); 

Bạn sẽ được surpr ised biết rằng phương pháp mở rộng này rất hiệu quả (chắc chắn hiệu quả hơn thì Regex) vì vậy tôi sẽ đề nghị bạn sử dụng nó;)

Cập nhật

Tôi đồng ý rằng đây là một cách tiếp cận chỉ tiếng Anh nhưng để làm cho nó tương thích Unicode tất cả các bạn phải làm là thay thế:

(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') 

với:

char.IsLetter(c) 

nào suppor ts Unicode,.Net Ngoài ra cung cấp cho bạn char.IsSymbolchar.IsLetterOrDigit cho sự đa dạng của các trường hợp

+0

Tôi không nghĩ chữ số là một phần của một từ - nhưng tôi đoán điều đó là tùy thuộc vào OP – Hogan

+0

Tôi nói rằng điều đó tùy thuộc vào anh ta, anh ấy có thể thay đổi regex theo ý muốn. –

+2

Vấn đề duy nhất tôi thấy là giải pháp của bạn sẽ cắt bỏ các dấu nháy đơn của các cơn co thắt. Ví dụ thay đổi "không phải" thành "isnt" –

6

Chỉ cần thêm một biến thể của câu trả lời @ Adam Fridental của mà là rất tốt, bạn có thể thử Regex này:

var text = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'"; 

var matches = Regex.Matches(text, @"\w+[^\s]*\w+|\w"); 

foreach (Match match in matches) { 
    var word = match.Value; 
} 

Tôi tin rằng đây là ngắn nhất regEx rằng sẽ nhận được tất cả những lời

\w+[^\s]*\w+|\w 
+1

Rất đẹp.Nhưng như tôi đã nói trong câu trả lời của tôi, có một vấn đề khi giải quyết vấn đề này với regex - thời gian cần, tôi đã kiểm tra và phương pháp mở rộng mà tôi đã viết trong câu trả lời của tôi là ~ X7 nhanh hơn sau đó phân tích cú pháp biểu thức chính quy. –

+1

Cảm ơn bạn đã lược tả chúng, tôi đã học được điều gì đó mới mẻ hôm nay :) Bạn có upvote của tôi. Tôi muốn tiếp tục tranh cãi (như bản chất của tôi) cho Regex để giảm độ phức tạp của mã, nhưng phương pháp của bạn khá ngắn và hầu hết mọi người không thấy regex thân thiện như tôi. ồ. –

+1

Tôi đồng ý rằng Refex rất tuyệt. Khi bạn có một giây chờ đợi :) –

0

Bạn có thể thử sử dụng một regex để loại bỏ các dấu nháy mà không được bao quanh bởi chữ cái (tức là dấu nháy đơn) và sau đó sử dụng phương pháp Char tĩnh để tước tất cả các ot nhân vật của cô ấy. Bằng cách gọi regex trước, bạn có thể giữ các dấu nháy đơn (ví dụ: can't) nhưng xóa các dấu nháy đơn như trong 'Oh.

string myText = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'"; 

Regex reg = new Regex("\b[\"']\b"); 
myText = reg.Replace(myText, ""); 

string[] listOfWords = RemoveCharacters(myText); 

public string[] RemoveCharacters(string input) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach (char c in input) 
    { 
     if (Char.IsLetter(c) || Char.IsWhiteSpace(c) || c == '\'') 
      sb.Append(c); 
    } 

    return sb.ToString().Split(' '); 
} 
1

Nếu bạn không muốn sử dụng một đối tượng Regex, bạn có thể làm một cái gì đó giống như ...

string mystring="Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad."; 
List<string> words=mystring.Replace(",","").Replace(":","").Replace(".","").Split(" ").ToList(); 

Bạn vẫn sẽ phải xử lý các dấu nháy đơn dấu ở phần cuối của "rằng , '"

1

Đây là một giải pháp, tôi không sử dụng bất kỳ lớp hoặc phương thức trợ giúp nào.

 public static List<string> ExtractChars(string inputString) { 
      var result = new List<string>(); 
      int startIndex = -1; 
      for (int i = 0; i < inputString.Length; i++) { 
       var character = inputString[i]; 
       if ((character >= 'a' && character <= 'z') || 
        (character >= 'A' && character <= 'Z')) { 
        if (startIndex == -1) { 
         startIndex = i; 
        } 
        if (i == inputString.Length - 1) { 
         result.Add(GetString(inputString, startIndex, i)); 
        } 
        continue; 
       } 
       if (startIndex != -1) { 
        result.Add(GetString(inputString, startIndex, i - 1)); 
        startIndex = -1; 
       } 
      } 
      return result; 
     } 

     public static string GetString(string inputString, int startIndex, int endIndex) { 
      string result = ""; 
      for (int i = startIndex; i <= endIndex; i++) { 
       result += inputString[i]; 
      } 
      return result; 
     } 
Các vấn đề liên quan