NSPredicate SELF CONTAINS[c] returns 值首先包含在较长的文本中

NSPredicate SELF CONTAINS[c] returns value contained in longer text first

我正在使用 UISearchBar 对 UITableView 进行排序。 table 填充的数组中的每个值最多可以有 3 个单词

@"Pineapple"、@"Pineapple Green"、@"Apple Green"、@"Apple Green, Raw"...

我正在使用下面的 NSPredicate 方法:

 NSArray *words = [text componentsSeparatedByString:@" "];
    NSMutableArray *predicateList = [NSMutableArray array];
    for (NSString *word in words) {
        if ([word length] > 0) {
            NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF contains[c] %@", word];
            [predicateList addObject:pred];
        }
    }
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateList];
    NSLog(@"%@", predicate);

它有效,但它不会按最接近的亲戚对值进行排序,而是始终按其索引从数组中获取第一个匹配值。这意味着,如果我想查找 "apple" 并在 SearchBar 中键入它,结果将是:

Pineapple
Pineapple Green
Apple
Apple Green

我不能使用谓词 BEGINSWITH,因为如果我搜索 "Green Apple",结果将是空白。在这种特殊情况下,我可以使用升序对结果进行排序,但在另一种情况下(例如 TEA),它不起作用,因为字符串 "TEA" 包含在其他词(例如 STEAM)中,并且它会排在第一位。

我这里没有选择,有没有办法根据搜索输出逻辑结果?如果要查找 "Apple":

Apple    
Apple Green

//-------- 附加

感谢大家的回复。我在考虑自定义逻辑并想出了这个。我确信它是脏代码并且可以改进,但它现在的性能要好得多。它仍然没有以有组织的方式显示结果,但是搜索现在包含所有相关的项目,无论您以什么顺序输入搜索:

NSArray *words = [text componentsSeparatedByString:@" "];

    NSString *word1;
    NSString *word2;
    NSString *word3;
    NSPredicate *predicate;

    if (words.count == 1) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ OR SELF LIKE[cd] %@", word1, word1];
    }
    else if (words.count == 2) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        word2 = [NSString stringWithFormat:@"%@", [words objectAtIndex:1]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2];
    }
    else if (words.count == 3) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        word2 = [NSString stringWithFormat:@"%@", [words objectAtIndex:1]];
        word3 = [NSString stringWithFormat:@"%@", [words objectAtIndex:2]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2,word3];
    }
    NSArray *sortedArray = [self.allItemsArray filteredArrayUsingPredicate:predicate];
    filteredTableData = [sortedArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

如果有人知道如何对结果进行排序以获得最接近的匹配,请分享。谢谢

解决这个问题的一种方法是将谓词应用于 NSSet 而不是 NSArray。像这样:

     NSSet *tempSet = [NSSet setWithArray:words];
     tempSet = [tempSet filteredSetUsingPredicate:predicate];
     resultsArray = [tempSet allObjects];

希望对您有所帮助。

轰!我知道了!我只需要添加 NSSortDescriptor。现在看起来很简单:

NSArray *words = [text componentsSeparatedByString:@" "];

    NSString *word1;
    NSString *word2;
    NSString *word3;
    NSPredicate *predicate;

    if (words.count == 1) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ OR SELF LIKE[cd] %@", word1, word1];

    }
    else if (words.count == 2) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        word2 = [NSString stringWithFormat:@"%@", [words objectAtIndex:1]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2];

    }
    else if (words.count == 3) {
        word1 = [NSString stringWithFormat:@"%@", [words objectAtIndex:0]];
        word2 = [NSString stringWithFormat:@"%@", [words objectAtIndex:1]];
        word3 = [NSString stringWithFormat:@"%@", [words objectAtIndex:2]];
        predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2,word3];

    }
    NSArray *sortedArray = [self.allItemsArray filteredArrayUsingPredicate:predicate];
    NSSortDescriptor *lengthSorter = [NSSortDescriptor sortDescriptorWithKey:@"length" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:lengthSorter];
    filteredTableData = [sortedArray sortedArrayUsingDescriptors:sortDescriptors];

它现在按照我想要的方式工作了!但如果您有任何改进建议,请分享!

谢谢

包含循环的解决方案,其中搜索词的数量无关紧要。

NSArray *words = [text componentsSeparatedByString:@" "];
NSMutableArray *andPredicateSections = [NSMutableArray arrayWithCapacity:1];

for (NSString *nextWord in words) {
    NSPredicate *aPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", nextWord];
    [andPredicateSections addObject:aPredicate];
}

NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:andPredicateSections];
NSArray *sortedArray = [self.allItemsArray filteredArrayUsingPredicate:predicate];