2013-07-26 34 views
6

Tôi đang cố lọc một tập hợp các chuỗi bằng danh sách "bộ lọc" ... danh sách các từ xấu. Chuỗi chứa một từ trong danh sách mà tôi không muốn.Làm cách nào để so sánh chuỗi với danh sách "bộ lọc" trong LINQ?

tôi đã nhận được cho đến nay, Lời xấu ở đây là "frakk":

string[] filter = { "bad", "words", "frakk" }; 

string[] foo = 
{ 
    "this is a lol string that is allowed", 
    "this is another lol frakk string that is not allowed!" 
}; 

var items = from item in foo 
      where (item.IndexOf((from f in filter select f).ToString()) == 0) 
      select item; 

Nhưng làm việc aint này, tại sao?

Trả lời

9

Bạn có thể sử dụng Any + Contains:

var items = foo.Where(s => !filter.Any(w => s.Contains(w))); 

nếu bạn muốn so sánh trường insensitively:

var items = foo.Where(s => !filter.Any(w => s.IndexOf(w, StringComparison.OrdinalIgnoreCase) >= 0)); 

Cập nhật: Nếu bạn muốn exlude câu mà ít nhất một từ nằm trong danh sách bộ lọc bạn có thể sử dụng String.Split()Enumerable.Intersect:

var items = foo.Where(sentence => !sentence.Split().Intersect(filter).Any()); 

Enumerable.Intersect là rất hiệu quả vì nó sử dụng Set dưới mui xe. hiệu quả hơn là đặt chuỗi dài đầu tiên. Do thực thi trì hoãn của Linq dừng ở từ khớp đầu tiên.

(lưu ý rằng "trống rỗng" Split bao gồm ký tự trắng-không gian khác như tab hoặc newline)

+1

Sẽ không giải pháp này bắt một phần từ? Ví dụ: nó sẽ gắn cờ 'badmitten' là một từ xấu – JaredPar

+0

@JaredPar: Đã chỉnh sửa câu trả lời của tôi để bao gồm cách tiếp cận từ. –

2

Vấn đề đầu tiên bạn cần phải giải quyết được phá vỡ câu vào một loạt các từ. Cách đơn giản nhất để làm điều này được dựa trên không gian

string[] words = sentence.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); 

Từ đó bạn có thể sử dụng một biểu thức LINQ đơn giản để tìm ra profanities

var badWords = words.Where(x => filter.Contains(x)); 

Tuy nhiên đây là một chút của một giải pháp nguyên thủy. Nó sẽ không xử lý một số trường hợp phức tạp mà bạn có thể cần phải suy nghĩ về

  • Có nhiều ký tự đủ điều kiện làm dấu cách. Giải pháp của tôi chỉ sử dụng ' '
  • Chia tách không xử lý các dấu câu. Vì vậy, dog! sẽ không được xem là dog. Có lẽ tốt hơn nhiều để chia tay từ trên ký tự pháp lý
+0

Việc ghép nối danh sách các từ xấu và đặt nó vào như một kết hợp regex có ý nghĩa hơn ở đây hơn là cố gắng lo lắng về tất cả các hoán vị khác nhau của phân tách từ? –

+0

@JimWooley có thể là cách tốt hơn để tiếp cận vấn đề. Esp cho rằng 'Regex' đã có sẵn các cơ chế phát hiện ranh giới từ (' \ b'). Tôi vẫn muốn biết thêm về kịch bản trước khi tôi đề nghị một regex mặc dù, tôi dự trữ chúng cho các kịch bản không quan trọng (tuyệt vời cho xác thực javascript nhanh nhưng xấu cho bất cứ điều gì trên máy chủ) – JaredPar

+0

Tại sao regexs phía máy chủ xấu? (Câu hỏi chính hãng) –

0

Lý do nỗ lực ban đầu của bạn không làm việc là dòng này:

(from f in filter select f).ToString() 

để đánh giá một loạt các tên kiểu mảng Iterator đó là ngụ ý của phần biểu thức LINQ. Vì vậy, bạn đang thực sự so sánh các ký tự của chuỗi sau:

System.Linq.Enumerable+WhereSelectArrayIterator``2[System.String,System.String]

chứ không phải là những lời của các bộ lọc khi kiểm tra cụm từ của bạn.

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