2011-11-07 30 views
11

Trong tiếng Do Thái, có một số nguyên âm nhất định mà NSPredicate không bỏ qua ngay cả khi sử dụng công cụ sửa đổi 'd' (dấu phụ không phân biệt) trong biến vị ngữ. Tôi đã nói rằng giải pháp là sử dụng các biểu thức thông thường để thực hiện tìm kiếm.Làm cách nào để sử dụng regex để tìm kiếm bỏ qua các ký tự nhất định bằng NSPredicate?

Làm cách nào để lấy chuỗi tìm kiếm và "sử dụng regex" để tìm kiếm văn bản hebrew có chứa nguyên âm, bỏ qua các nguyên âm đó?

Edit:

Nói cách khác, Nếu tôi muốn tìm kiếm các văn bản sau đây, bất chấp dấu gạch ngang và dấu sao, làm thế nào tôi làm như vậy sử dụng regex?

Ví dụ Text:

tôi w-en * t t-o st * o * r * -e vâng-ster * ngày.

Chỉnh sửa 2:

Về cơ bản, tôi muốn:

  1. Tham dự một chuỗi đầu vào từ một người dùng
  2. Hãy chuỗi để tìm kiếm
  3. Dùng regex dựa trên chuỗi tìm kiếm của người dùng để tìm kiếm các kết quả "chứa" trong khối văn bản lớn hơn. Các regex nên bỏ qua nguyên âm như được hiển thị ở trên.

Sửa 3:

Đây là cách tôi đang thực hiện tìm kiếm của tôi:

// 
// The user updated the search text 
// 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
shouldReloadTableForSearchString:(NSString *)searchString{ 

    NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy]; 

    if (self.filteredArray == nil) { 
     self.filteredArray = [[[NSMutableArray alloc ] init] autorelease]; 
    } 

    [filteredArray removeAllObjects]; 

    NSPredicate *predicate; 

    if (controller.searchBar.selectedScopeButtonIndex == 0) { 
     predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", searchString]; 
    }else if (controller.searchBar.selectedScopeButtonIndex == 1) { 
     predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", searchString];    
    }else if (controller.searchBar.selectedScopeButtonIndex == 2){ 
     predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString]; 
    }else{ 
     predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", searchString,searchString,searchString]; 
    } 

    for (Article *article in unfilteredResults) { 

     if ([predicate evaluateWithObject:article]) { 
      [self.filteredArray addObject:article]; 
     } 

    } 

    [unfilteredResults release]; 


    return YES; 
} 

Sửa 4:

Tôi không nhất thiết phải sử dụng regex cho điều này, đã được khuyên nên làm như vậy. Nếu bạn có một cách khác hoạt động, hãy tìm nó!

Sửa 5:

Tôi đã sửa đổi tìm kiếm của tôi trông như thế này:

NSInteger length = [searchString length]; 

NSString *vowelsAsRegex = @"[\\u5B0-\\u55C4]*"; 

NSMutableString *modifiedSearchString = [searchString mutableCopy]; 

for (int i = length; i > 0; i--) { 
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i]; 
} 

if (controller.searchBar.selectedScopeButtonIndex == 0) { 
      predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString]; 
     }else if (controller.searchBar.selectedScopeButtonIndex == 1) { 
      predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];    
     }else if (controller.searchBar.selectedScopeButtonIndex == 2){ 
      predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", modifiedSearchString]; 
     }else{ 
      predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString]; 
     } 

for (Article *article in unfilteredResults) { 
    if ([predicate evaluateWithObject:article]) { 
    [self.filteredArray addObject:article]; 
    }   
} 

Tôi vẫn đang thiếu một cái gì đó ở đây, những gì tôi cần phải làm gì để làm cho công việc này?

Sửa 6:

Được rồi, gần như ở đó. Tôi cần thực hiện thêm hai thay đổi để hoàn thành việc này.

Tôi cần có thể thêm các dải ký tự khác vào regex, có thể xuất hiện thay cho hoặc ngoài ký tự trong tập hợp khác. Tôi đã thay đổi phạm vi đầu tiên thành điều này:

[\u05b0-\u05c, \u0591-\u05AF]? 

Điều gì đó cho tôi biết điều này là không chính xác.

Ngoài ra, tôi cần phần còn lại của regex không phân biệt chữ hoa chữ thường. Tôi cần sử dụng công cụ sửa đổi nào để sử dụng với regex .* để làm cho nó không phân biệt chữ hoa chữ thường?

+0

bản sao có thể có của [NSPredicate và Regex] (http://stackoverflow.com/questions/2458881/nspredicate-and-regex) –

+0

Có thể là: 1. Xóa ký hiệu xấu (nguyên âm). 2. Thêm một cái gì đó như thế này: ". *?" sau mỗi nhân vật. 3. Tìm kiếm. Bạn có chấp nhận quyết định như vậy không? – Nekto

Trả lời

2

Câu trả lời này sẽ trả lời câu hỏi còn lại ở đâu. Vui lòng đọc điều đó cho ngữ cảnh.

Khi hóa ra, iOS có thể làm cho cụm từ thông dụng không phân biệt chữ hoa chữ thường bằng cách sử dụng công cụ sửa đổi Mục tiêu-C thành NSPredicate. Tất cả những gì còn lại là kết hợp hai phạm vi. Tôi nhận ra rằng họ thực sự là hai dãy liên tiếp. Mã cuối cùng của tôi trông giống như sau:

NSInteger length = [searchString length]; 

NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?"; //Cantillation: \u0591-\u05AF Vowels: \u05b0-\u05c 

NSMutableString *modifiedSearchString = [searchString mutableCopy]; 

for (int i = length; i > 0; i--) { 
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i]; 
} 

if (controller.searchBar.selectedScopeButtonIndex == 0) { 
    predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString]; 
}else if (controller.searchBar.selectedScopeButtonIndex == 1) { 
    predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[c] %@", modifiedSearchString];    
}else if (controller.searchBar.selectedScopeButtonIndex == 2){ 
    predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[c] %@", modifiedSearchString]; 
}else{ 
    predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[c] %@) OR (dvarTorahTitle CONTAINS[c] %@) OR (dvarTorahContent CONTAINS[c] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString]; 
} 

[modifiedSearchString release]; 

for (Article *article in unfilteredResults) { 
    if ([predicate evaluateWithObject:article]) { 
    [self.filteredArray addObject:article]; 
    }   
} 

Lưu ý rằng phần phạm vi của cụm từ thông dụng lặp lại chính nó. Điều này là bởi vì có thể có cả một dấu hiệu chưng cất và nguyên âm trên một chữ cái duy nhất. Bây giờ, tôi có thể tìm kiếm chữ hoa và chữ thường tiếng Anh, và tiếng Do Thái có hoặc không có nguyên âm và dấu hiệu chưng cất.

Tuyệt vời!

+0

Tuyệt vời mà bạn đã tìm thấy câu trả lời. Tôi đã không nhận ra rằng bạn cũng đang tìm kiếm trong văn bản tiếng Anh hoặc tiếng Do Thái với cantillation. Điều đó nói rằng, tôi có một cảm giác rằng bạn không có một giải pháp 100%. Ví dụ: câu thơ על פני המים. Chữ "מ" có nguyên âm, dấu và dagesh. Đó là 3, nhưng bạn cho phép chỉ 2. Ngoài ra, tôi không chắc chắn nếu nó hợp lệ Unicode để bắt đầu một chuỗi với nguyên âm, nhưng nếu có, bạn không bỏ nó ra. – JXG

+0

Điểm tốt. Bạn có nghĩ rằng nó có giá trị thêm một nhân vật thứ ba trong chuỗi regex? Có cách nào để chỉ định "không hoặc nhiều hơn, tối đa ba lần" không? – Moshe

+0

Tôi đề nghị chỉ sử dụng '*' như trước, nhưng tôi nghĩ '{0,3}' cũng sẽ hoạt động trong khoảng từ 0 đến 3 lần - không chắc chắn rằng bạn có thể sử dụng 0 với '{}'. – JXG

2

Các nguyên âm tiếng Hebrew cũng được định nghĩa trong Unicode: Table of Hebrew characters and Marks

Khi bạn nhận được chuỗi đầu vào từ người sử dụng, bạn có thể chèn các biểu thức chính quy [\u05B0-\u05C4]* ở giữa mỗi nhân vật, và trước và sau khi chuỗi. ([] nghĩa là khớp với bất kỳ ký tự nào được bao gồm, và * có nghĩa là không khớp hoặc nhiều lần xuất hiện của biểu thức.) Sau đó, bạn có thể tìm kiếm khối văn bản, sử dụng cụm từ này dưới dạng cụm từ thông dụng. Biểu thức này cho phép bạn tìm chuỗi chính xác từ đầu vào của người dùng. Người dùng cũng có thể chỉ định các nguyên âm bắt buộc, biểu thức này sẽ tìm thấy.

Tôi nghĩ rằng thay vì cố gắng "phớt lờ" nguyên âm, sẽ dễ dàng hơn khi loại bỏ nguyên âm khỏi cả khối văn bản lớn và chuỗi của người dùng. Sau đó, bạn có thể tìm kiếm chỉ các chữ cái, như thường lệ. Phương pháp này sẽ hoạt động nếu bạn không cần hiển thị văn bản được thanh âm mà người dùng đã tìm thấy.

+0

Trông giống như một ý tưởng hay. Cách hiệu quả để chuyển đổi chuỗi tìm kiếm thành cụm từ thông dụng là gì? – Moshe

+0

@Moshe, tôi không biết cách hiệu quả (hoặc thậm chí tốt) là gì. Bạn có thể sử dụng 'NSMutableString' và' insertString: atIndex: ', tôi giả sử đếm ngược trong một vòng lặp từ cuối chuỗi. Tôi không biết nếu đó là rất tốt, mặc dù. – JXG

+0

Tôi có một giải pháp làm việc, điều này hữu ích, nhiều hơn nữa khi tôi đến máy tính. – Moshe

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