如何使用NSPredicate从数组中选择确切的短语?

时间:2021-09-04 22:46:35

I am using an NSPredicate to filter an NSDictionary by a list of states and countries.

我正在使用一个NSPredicate来过滤一个NSDictionary,由一个国家和国家的列表。

All the data are stored in a comma separated array: @"Alabama", @"Alaska", @"Arizona", @"Arkansas", @"California", @"Colorado", etc

所有数据都存储在一个逗号分隔的数组中:@“Alabama”、@“Alaska”、@“Arizona”、@“Arkansas”、@“California”、@“Colorado”等等

However, there are 2 situations where duplicates are occurring. The state "New Mexico" contain the word "Mexico", and "Arkansas" contains the word "Kansas.

然而,有两种情况出现重复。“新墨西哥州”包含“墨西哥”,“阿肯色州”包含“堪萨斯州”。

Here's the basic code I'm using to define the predicate.

下面是我用来定义谓词的基本代码。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location contains[c] %@", @"Kansas"];

How can I make sure "Kansas" doesn't return objects with "Arkansas"? Using BEGINSWITH or LIKE doesn't work because the list begins with some other state.

我怎样才能确保“堪萨斯”不会返回带有“阿肯色”的物品呢?使用BEGINSWITH或LIKE是行不通的,因为列表是从其他状态开始的。

Thanks!

谢谢!

7 个解决方案

#1


4  

Let's see if I understand correctly. You have a dictionary, where there is a key "Location" whose object is a string with comma separated state names. Sounds like you need a regular expression to match.

让我们看看我是否理解对了。您有一个字典,其中有一个键“Location”,它的对象是一个带有逗号分隔的状态名的字符串。听起来你需要一个正则表达式来匹配。

NSString* expr = [NSString stringWithFormat:@"^%1$@.*|.*, %1$@.*", @"Kansas"]  
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Location MATCHES[c] %@", expr];

Now, here is how it would behave for different examples:

下面是不同例子的表现:

@{@"Location": @"Kansas, Arkansas, Alabama"} //Pass
@{@"Location": @"Alabama, Kansas"} //Pass
@{@"Location": @"Arkansas, Alabama"} //Fail

The regular expression ^%1$@.*|.*, %1$@.* tests if the word provided is either at the start of the string or followed by characters and ", ", which puts it in the middle. %1$@ takes the first param, so that it can be used multiple times instead of prividing the same string several times.

正则表达式$ @ ^ % 1。* |。* % 1 $ @。*测试所提供的单词是否在字符串的开头,或后跟字符和“,”,这将把它放在中间。%1$@获取第一个参数,因此可以多次使用它,而不是多次使用相同的字符串。

#2


1  

May be this helps?

这可能会帮助吗?

// If I understood correctly, then your locations in the dictionary are like this
NSString *locations = @"Alabama, Alaska, Arizona, Arkansas";

NSString *trimmedLocations = [locations stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *compoments = [[trimmedLocations componentsSeparatedByString:@","] mutableCopy];   
//now in components we have this: @[@"Alabama", @"Alaska", @"Arizona", @"Arkansas", @"California", @"Colorado"]

[compoments filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isEqualToString:@"Kansas"];
}]];

BOOL match = compoments.count;
if (match) {
    //do something with locations...
}

#3


1  

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Location IN %@", myStatesArray];

#4


1  

I think what you want is an exact match predicate search:

我想你想要的是一个精确的匹配谓词搜索:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location == [c] %@", @"Kansas"];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location = [c] %@", @"Kansas"];

Am I understanding your question incorrectly?

我理解错你的问题了吗?

#5


1  

It will work:

它将工作:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entity.name LIKE[c] %@", myString];

LIKE matches strings with ? and * as wildcards. The [c] indicates that the comparison should be case insensitive.

比如匹配字符串?和*通配符。[c]表示比较应该不区分大小写。

If you don't want ? and * to be treated as wildcards, you can use == instead of LIKE:

如果你不想?将*视为通配符,可以使用==代替LIKE:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entity.name ==[c] %@", myString];

More info in the NSPredicate Predicate Format String Syntax documentation.

更多关于NSPredicate谓词格式字符串语法文档的信息。

#6


1  

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location matches[c] %@", @"Kansas"];

This must help you with the fix.

这一定会对您的修复有所帮助。

#7


1  

Try your predicate with matches keyword, it will give you the exact result match and accordingly you can remove the duplicate occurence in the predicate as below-

使用matches关键字试试你的谓词,它会给你精确的结果匹配,因此你可以删除谓词中的重复出现,如下所示

NSArray *yourArr=@[@"Alabama", @"Alaska", @"Arizona", @"Arkansas", @"California", @"Colorado"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location contains[CD] %@", @"Kansas"];
NSMutableArray *filterdArray=[yourArr filteredArrayUsingPredicate:predicate];
if(filterdArray.count>0)
{
NSLog(@"Invalid State");
 }

#1


4  

Let's see if I understand correctly. You have a dictionary, where there is a key "Location" whose object is a string with comma separated state names. Sounds like you need a regular expression to match.

让我们看看我是否理解对了。您有一个字典,其中有一个键“Location”,它的对象是一个带有逗号分隔的状态名的字符串。听起来你需要一个正则表达式来匹配。

NSString* expr = [NSString stringWithFormat:@"^%1$@.*|.*, %1$@.*", @"Kansas"]  
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Location MATCHES[c] %@", expr];

Now, here is how it would behave for different examples:

下面是不同例子的表现:

@{@"Location": @"Kansas, Arkansas, Alabama"} //Pass
@{@"Location": @"Alabama, Kansas"} //Pass
@{@"Location": @"Arkansas, Alabama"} //Fail

The regular expression ^%1$@.*|.*, %1$@.* tests if the word provided is either at the start of the string or followed by characters and ", ", which puts it in the middle. %1$@ takes the first param, so that it can be used multiple times instead of prividing the same string several times.

正则表达式$ @ ^ % 1。* |。* % 1 $ @。*测试所提供的单词是否在字符串的开头,或后跟字符和“,”,这将把它放在中间。%1$@获取第一个参数,因此可以多次使用它,而不是多次使用相同的字符串。

#2


1  

May be this helps?

这可能会帮助吗?

// If I understood correctly, then your locations in the dictionary are like this
NSString *locations = @"Alabama, Alaska, Arizona, Arkansas";

NSString *trimmedLocations = [locations stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *compoments = [[trimmedLocations componentsSeparatedByString:@","] mutableCopy];   
//now in components we have this: @[@"Alabama", @"Alaska", @"Arizona", @"Arkansas", @"California", @"Colorado"]

[compoments filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isEqualToString:@"Kansas"];
}]];

BOOL match = compoments.count;
if (match) {
    //do something with locations...
}

#3


1  

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Location IN %@", myStatesArray];

#4


1  

I think what you want is an exact match predicate search:

我想你想要的是一个精确的匹配谓词搜索:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location == [c] %@", @"Kansas"];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location = [c] %@", @"Kansas"];

Am I understanding your question incorrectly?

我理解错你的问题了吗?

#5


1  

It will work:

它将工作:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entity.name LIKE[c] %@", myString];

LIKE matches strings with ? and * as wildcards. The [c] indicates that the comparison should be case insensitive.

比如匹配字符串?和*通配符。[c]表示比较应该不区分大小写。

If you don't want ? and * to be treated as wildcards, you can use == instead of LIKE:

如果你不想?将*视为通配符,可以使用==代替LIKE:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entity.name ==[c] %@", myString];

More info in the NSPredicate Predicate Format String Syntax documentation.

更多关于NSPredicate谓词格式字符串语法文档的信息。

#6


1  

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location matches[c] %@", @"Kansas"];

This must help you with the fix.

这一定会对您的修复有所帮助。

#7


1  

Try your predicate with matches keyword, it will give you the exact result match and accordingly you can remove the duplicate occurence in the predicate as below-

使用matches关键字试试你的谓词,它会给你精确的结果匹配,因此你可以删除谓词中的重复出现,如下所示

NSArray *yourArr=@[@"Alabama", @"Alaska", @"Arizona", @"Arkansas", @"California", @"Colorado"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Location contains[CD] %@", @"Kansas"];
NSMutableArray *filterdArray=[yourArr filteredArrayUsingPredicate:predicate];
if(filterdArray.count>0)
{
NSLog(@"Invalid State");
 }