10

如何构造一个 NSPredicate 来查找 Arrays 对象中任何位置的搜索词?我不能很好地解释它,所以这里有一个例子。

NSArray *array = @[@"Test String: Apple", @"Test String: Pineapple", @"Test String: Banana"];
NSString *searchText = @"Apple";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchText];
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate];
NSLog(@"filteredArray: %@", filteredArray);

// filteredArray: (
//    "Test String: Apple",
//    "Test String: Pineapple"
// )

但如果我使用NSString *searchText = @"Test Str Appl";我得到零结果。我希望它匹配这个字符串的相同结果。

我正在寻找的是一个类似于 Xcode 中的“快速打开”菜单的搜索功能,在这里搜索字符串的措辞是否正确无关紧要,只是字母的顺序正确作为匹配项。我真的希望这是有道理的。

打开快速菜单

4

2 回答 2

20

谓词中的LIKE字符串比较允许使用通配符*?,其中*匹配 0 个或多个字符。因此,如果您将搜索文本转换为

NSString *searchWithWildcards = @"*T*e*s*t* *S*t*r*A*p*p*l*";

*通过在开头、所有字符之间和原始搜索文本的末尾插入 a使用类似这样的东西

NSMutableString *searchWithWildcards = [NSMutableString stringWithFormat:@"*%@*", self.searchField.text];
if (searchWithWildcards.length > 3)
    for (int i = 2; i < self.searchField.text.length * 2; i += 2)
        [searchWithWildcards insertString:@"*" atIndex:i];

那么你可以使用

[NSPredicate predicateWithFormat:@"SELF LIKE[cd] %@", searchWithWildcards];

谓词以给定的顺序搜索字符,它们之间有任意其他字符。


例如,可以使用以下代码完成转换:

NSMutableString *searchWithWildcards = [@"*" mutableCopy];
[searchText enumerateSubstringsInRange:NSMakeRange(0, [searchText length])
                   options:NSStringEnumerationByComposedCharacterSequences
                usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                    [searchWithWildcards appendString:substring];
                    [searchWithWildcards appendString:@"*"];
                }];
于 2013-02-26T14:26:25.057 回答
0

因为我的objcC读的不太好,所以我自己写了通配符函数。开始了:

斯威夫特 5

CoreData 被提取到初始化的数组中

var originalArray: [NSManagedObject] = []


extension myViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        filteredArray.removeAll(keepingCapacity: true)
        if searchController.searchBar.text!.isEmpty {
            filteredArray = originalArray
        } else {
            let filter = searchController.searchBar.text!
            var filterWithWildcards = ""
            for i in 0 ..< filter.length {
                if i == 0 {
                    filterWithFormat = "*"
                }
                filterWithFormat += filter[i] + "*"
            }
            print("filter: \(filter); filterWithWildcards: \(filterWithWildcards)") // filter: Mxmstrmnn; filterWithFormat: *M*x*m*s*t*r*m*n*n*
            myPredicate = NSPredicate(format: "EnterYourAttributeNameOfCoreDataEntity LIKE[c] %@", filterWithWildcards)
            let array = (people as NSArray).filtered(using: myPredicate!)
            filteredArray = array as! [NSManagedObject]
        }
        myTableView.reloadData()
}}

只要我保持字母顺序,filteredArray 中的结果就会找到Max Mustermann 。

为了获得过滤器[i]的索引字母,我使用了来自这里的字符串扩展https://stackoverflow.com/a/26775912/12035498

于 2020-02-29T00:55:01.970 回答