2012-04-11 65 views
5

Tôi cần kiểm tra xem chuỗi có chứa bất kỳ từ nào không.C# - Cách nhanh nhất để tìm một tập hợp các chuỗi trong một chuỗi khác

Tiếp theo một số lời khuyên từ một câu hỏi ở đây, tôi đã thực hiện một HashSet chứa dòng chữ:

HashSet<string> swearWords = new HashSet<string>() { "word_one", "word_two", "etc" }; 

Bây giờ tôi cần phải xem nếu bất kỳ giá trị chứa trong swearWords là trong chuỗi của tôi.

Tôi đã nhìn thấy nó được thực hiện theo chiều ngược lại, ví dụ:

swearWords.Contains(myString) 

Nhưng điều này sẽ trả về false.

Cách nhanh nhất để kiểm tra xem có bất kỳ từ nào trong HashSet nằm trong số myString không?

NB: Tôi hình tôi có thể sử dụng vòng lặp foreach để kiểm tra từng từ, và ngắt nếu tìm thấy kết quả phù hợp, tôi chỉ tự hỏi có cách nào nhanh hơn không.

+0

Tại sao các bạn sử dụng một 'HashSet'? Có thể dễ dàng hơn để sử dụng 'Danh sách 'tại đây. Và sau đó chia 'myString' thành danh sách và thực hiện so sánh cần thiết. – SkonJeet

+1

@SkonJeet: nếu danh sách các từ chửi thề lớn, việc kiểm tra ngăn chặn sẽ nhanh hơn cho một 'HashSet' hơn là' Danh sách' - và tôi không thể thấy rằng một 'Danh sách' sẽ làm cho nó dễ dàng hơn *. –

+0

Ban đầu tôi đã sử dụng một danh sách và sau đó chuyển đổi nó thành một HashSet khi tôi đọc chúng nhanh hơn để kiểm tra các giá trị trong – surfitscrollit

Trả lời

6

Bạn có thể thử một regex, nhưng tôi không chắc chắn đó là nhanh hơn.

Regex rx = new Regex("(" + string.Join("|", swearWords) + ")"); 
rx.IsMatch(myString) 
+2

+1 - Swear Tuy nhiên, thực tế là không thể đánh bại người dùng bằng thuật toán tĩnh và danh sách từ. –

9

Nếu bạn đặt thề của bạn trong một IEnumerable <> đựng thực hiện:

var containsSwears = swarWords.Any(w => myString.Contains(w)); 

Lưu ý: HashSet <> thực hiện IEnumerable <>

+2

'HashSet ' hiện thực hiện 'IEnumerable '. (Và bạn cần phải xem ra cho vấn đề Scunthorpe nếu bạn đang sử dụng phương pháp này: http://en.wikipedia.org/wiki/Scunthorpe_problem) – LukeH

+0

@ LukeH: điểm tốt nhưng vượt ra ngoài phạm vi của cuộc thảo luận này. Có lẽ tốt hơn như một bình luận về câu hỏi. +1 – Sprague

+0

lol @ scunthorpe, tên hay. Tuy nhiên, nếu logic của bạn để phá vỡ các từ hoạt động, bạn nên rõ ràng về vấn đề đó bởi vì bạn đang kiểm tra toàn bộ các từ, không phải chuỗi trong các từ. Một vấn đề bạn có thể có là phù hợp với trường hợp nhạy cảm của các từ hoặc từ mà sử dụng leet nói. –

3

Bạn có thể chia "myString" thành loại IEnumerable và sau đó sử dụng "Overlaps" trên chúng?

http://msdn.microsoft.com/en-us/library/bb355623(v=vs.90).aspx

(T.B. lâu rồi không gặp ...)

EDIT: Chỉ cần nhận thấy lỗi trong câu trả lời trước đây của tôi.

+0

Hey Adam! Yeah, đó là heh – surfitscrollit

+0

Thực ra, tôi chỉ double checked, Overlaps trông giống như nó sẽ làm khá nhiều việc chính xác những gì bạn cần? – KingCronus

3

Vấn đề chính với các chương trình như vậy là xác định những gì một từ là trong bối cảnh của chuỗi bạn muốn kiểm tra .

  • Việc triển khai thực hiện như sử dụng input.Contains đơn giản là không có khái niệm về từ; họ sẽ "phát hiện" lời thề ngay cả khi đó không phải là ý định.
  • Từ ngắt trên khoảng trắng sẽ không cắt nó (cũng xem xét các dấu chấm câu, v.v.).
  • Vi phạm các ký tự không phải khoảng trắng sẽ tăng vấn đề văn hóa: nhân vật nào được coi là ký tự từ chính xác?

Giả sử danh sách từ dừng của bạn chỉ sử dụng bảng chữ cái Latinh, một lựa chọn thực tế là giả định rằng các từ là chuỗi chỉ bao gồm các ký tự latin.Vì vậy, một giải pháp khởi đầu hợp lý sẽ là

var words = Regex.Split(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Pc}\p{Lm}]", myString); 

Các regex trên là lớp chuẩn \W sửa đổi để không bao gồm chữ số; để biết thêm thông tin, hãy xem http://msdn.microsoft.com/en-us/library/20bw873z.aspx. Đối với các cách tiếp cận khác, xem this question và có thể liên kết CodeProject được cung cấp trong câu trả lời được chấp nhận.

Sau khi chia chuỗi đầu vào, bạn có thể duyệt qua words và thay thế những phù hợp với bất cứ điều gì trong danh sách của bạn (sử dụng swearWords.Contains(word) để kiểm tra) hoặc đơn giản là phát hiện nếu có bất kỳ trận đấu nào cả với

var anySwearWords = words.Intersect(swearWords).Any(); 
Các vấn đề liên quan