2013-03-05 41 views
5

Tôi đang cố gắng cải thiện hiệu suất của một số mã. Có vẻ như sau:Làm cách nào để xác định xem một chuỗi không phải là cụm từ thông dụng?

public boolean isImportant(String token) { 
    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    } 
} 

Điều tôi nhận thấy là nhiều Mẫu có vẻ là các chuỗi ký tự đơn giản không có cấu trúc biểu thức chính quy. Vì vậy, tôi muốn chỉ đơn giản là lưu trữ chúng trong một danh sách riêng biệt (importantList) và làm một bài kiểm tra bình đẳng thay vì thực hiện một mô hình phù hợp đắt tiền hơn, chẳng hạn như sau:

public boolean isImportant(String token) { 
    if (importantList.contains(token)) return true; 

    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    }   
} 

Làm thế nào để lập trình xác định xem một chuỗi đặc biệt không chứa cấu trúc cụm từ thông dụng?

Chỉnh sửa: Tôi nên thêm rằng câu trả lời không cần phải nhạy cảm với hiệu suất. (tức là các biểu thức thông thường có thể được sử dụng) Tôi chủ yếu quan tâm đến hiệu năng của isImportant() vì nó được gọi là hàng triệu lần, trong khi sự khởi tạo của các mẫu chỉ được thực hiện một lần.

+1

Sẽ không làm biểu thức chính quy trên một chuỗi để xác định xem đó có phải là cụm từ thông dụng mỗi lần tồi tệ hơn nhiều so với việc sử dụng từng chuỗi như một cụm từ thông dụng không? –

+3

@MikeM: Đó không phải là những gì anh ấy hỏi. 'hello' là một regex hoàn toàn hợp lệ. –

+0

Không thể (ít nhất là không dễ dàng hoặc đáng giá, trừ khi bạn tìm thấy một số mẫu trong văn bản chuỗi đồng bằng). Một chuỗi ký tự đơn giản là một mẫu regex hợp lệ. – AC1

Trả lời

3

Sẽ rất khó khăn. Bạn có thể kiểm tra sự không hiện diện của bất kỳ metacharacters regex nào; phải là một phép tính xấp xỉ tốt:

Pattern regex = Pattern.compile("[$^()\\[\\]{}.*+?\\\\]"); 
Matcher regexMatcher = regex.matcher(subjectString); 
regexIsLikely = regexMatcher.find(); 

Cho dù đó có phải là một câu hỏi khác hay không. Bạn có chắc chắn một trận đấu regex là chậm hơn so với một tra cứu danh sách (đặc biệt là kể từ khi bạn sẽ làm một trận đấu regex sau đó trong nhiều trường hợp anyway)? Tôi muốn đặt cược nó nhanh hơn nhiều chỉ để giữ cho phù hợp với regex.

+0

Đây là giải pháp tôi đã thực hiện. Điều thú vị là tôi đã giảm thời gian xử lý khoảng 50%. –

4

Tôi thường ghét câu trả lời cho biết điều này nhưng ...

Đừng làm điều đó.

Nó có thể sẽ không làm cho mã chạy nhanh hơn, trên thực tế nó thậm chí có thể khiến chương trình mất nhiều thời gian hơn.

nếu bạn thực sự cần tối ưu hóa mã của mình, có khả năng nhiều địa điểm hiệu quả hơn nhiều nơi bạn có thể đến.

+0

Tôi có ý định gửi hồ sơ để trả lời câu hỏi liệu việc tối ưu hóa có ý nghĩa hay không. –

2

Không có cách nào để xác định nó vì mọi mẫu regex không có gì khác ngoài một chuỗi. Hơn nữa có được gần như không có khác biệt hiệu suất như regex là thông minh hiện nay và tôi khá chắc chắn, nếu mô hình và nguồn dài là như nhau, kiểm tra chứng khoán là lần đầu tiên sẽ được thực hiện

+1

Nó phụ thuộc, nhưng tôi ước tính rằng Java cố gắng thực hiện regex DFA hiệu quả hơn trước tiên và chỉ hoán đổi thành NFA nếu biểu thức yêu cầu nó (chẳng hạn như nếu nó bao gồm lookaround) –

1

Đây là sai

for (Pattern pattern : patterns) 

bạn nên tạo một regex lớn HOẶC tất cả các mẫu; sau đó cho mỗi đầu vào, bạn chỉ khớp một lần.

+0

Cảm ơn. Tôi thực sự đã làm điều đó và nó bật ra rằng bằng cách sử dụng một mô hình khổng lồ là khoảng 1/3 nhanh hơn so với kết hợp với nhiều mô hình nhỏ. –

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