NSArray with NSPredicate using NOT IN
What about NOT (CategoryID IN %@)
?
Using NSPredicate to filter an NSArray of objects based on a property which is an NSDictionary
You don't provide any code about you're using NSPredicate
, so I wrote a simple example. Maybe this will help you.
@objc class Dummy: NSObject {
let propertyOne: Int = 1
let propertyTwo: Int = 1
let propertyThree: NSDictionary
init(dict: NSDictionary) {
propertyThree = dict
super.init()
}
}
let arr: NSArray = [
Dummy(dict: ["keyOne" : "one"]),
Dummy(dict: ["keyOne" : "two"]),
Dummy(dict: ["keyOne" : "three"]),
Dummy(dict: ["keyOne" : "one"]),
Dummy(dict: ["keyOne" : "five"])
]
let predicate = NSPredicate(format: "SELF.propertyThree.keyOne == 'one'")
let results = arr.filteredArrayUsingPredicate(predicate)
print(results)
Filter NSArray based on another array using predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]];
NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];
complete example
@interface Alpha : NSObject
@property (nonatomic, copy) NSString *username;
-(instancetype) initWithUsername:(NSString *)username;
@end
@implementation Alpha
-(instancetype) initWithUsername:(NSString *)username
{
self = [super init];
if (self) {
self.username = username;
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username];
}
@end
NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"], [[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"z"], [[Alpha alloc] initWithUsername:@"f"], [[Alpha alloc] initWithUsername:@"e"]];
NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"f"]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]];
NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];
NSLog(@"%@", remaining_usernames);
prints
(
"Alpha: a",
"Alpha: z",
"Alpha: e"
)
Using NSPredicate to find elements in an NSArray similar to SQL WHERE IN clause
You can use NSCompoundPredicate
to merge together various NSPredicate
objects like this:
NSMutableArray *predicates = [NSMutableArray array];
[predicates addObject:[NSPredicate predicateWithFormat:@"tag == %@", @"iphone"]]];
[predicates addObject:[NSPredicate predicateWithFormat:@"tag == %@", @"apple"]]];
[predicates addObject:[NSPredicate predicateWithFormat:@"tag == %@", @"music"]]];
//Create a predicate using AND
NSPredicate *compoundANDpred = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
//Create a predicate using OR
NSPredicate *compoundORpred = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
or you could use a predicate with ANY and IN, as outlined in some of the other answers.
Filtering a large NSArray with NSPredicate
Solving this problem is easy if you iterate the array yourself using a block predicate. At some point a formatted NSPredicate would have to boil down to this, so there shouldn't be much of a performance hit. -[NSString rangeOfString:]
can be used to test for inclusion of the string.
return [_words filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL (id evaluatedString, NSDictionary *bindings) {
return string.length > 2 && [string rangeOfString:evaluatedString].location != NSNotFound;
}]];
Filter NSArray with NSPredicate inexact/similar match?
You have two problems (a) the match is wrong and (b) you have nested arrays.
(a) [cd]
means ignore case and diacritics, not punctuation and whitespace. A solution here is to use a regular expression and MATCHES[CD]
as the predicate. You need a regular expression which will match the terms you are looking for. A basic re is:
@"fullmetal[^a-z]*alchemist[^a-z]*brotherhood"
where [^a-z]*
matches zero or more (*
) characters from the set [...]
of every character which is not (^
) a letter a-z
.
While this works it probably matches far more than you wish - you should refine the regular expression.
(b) The error you got Can't do regex matching on object...
is because you cannot match a regular expression against an array, and the elements of your array are themselves array. You can address this using a simple loop over the elements, something along the lines of:
NSMutableArray *filtered = [NSMutableArray new]; // allocate an empty mutable array in which to accumulate the matches
for(NSArray *subArray in arraytoEvaluate) // loop over each sub array
[filtered addObjectsFromArray:[subArray filteredArrayUsingPredicate: titlePredicate]]; // and perform the predicate
HTH
NSArray filterArrayUsingPredicate never returning/ blocking execution
Change to this :
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'CNN'"];
In predicates, you must use query languages, in this case is a string literal: in Query languages two options: 'stringLitareal' or "stringLiteral" but this second don´t work because " is used in objective-C, you need to scape the ", that´s it: name == \"CNN\". You can test this, is the same:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == \"CNN\""];
More Info: https://developers.google.com/chart/interactive/docs/querylanguage#literals
Parentheses is not a problem (Query language). This also work : @"(name == 'CNN')"
Using NSPredicate to filter an NSMutableArray of NSDictionaries to find if a key exists
A dictionary delivers nil
as value for absent key. So simply compare the key against nil
.
NSPredicate *predicateString = [NSPredicate predicateWithFormat:@"%K==NULL", key]; // Dictionaries not having the key
NSPredicate *predicateString = [NSPredicate predicateWithFormat:@"%K!=NULL", key]; // Dictionaries having the key
Using NSPredicate to filter NSArray and find similar strings
What you are looking for is a custom predicate which uses a bounded Levenshtein Distance to filter out words that are sufficiently different from a target word.
Assuming you use an implementation of Levenshtein Distance as found in this gist, your code will look approximately like this:
NSPredicate *distancePredicate = [NSPredicate predicateWithBlock:^(NSString *name, NSDictionary<NSString *, id> *bindings) {
// key is the string you're looking for (e.g. 'nink')
NSString *key = bindings[@"key"];
// Calculate the Levenshtein Distance. This may be different depending
// on how you implement it. You may want to weight matchGain and
// missingCost differently.
NSInteger score = [key compareWithWord:name matchGain:0 missingCost:1];
// Only include words that are "close enough", i.e. within two a letter
// difference.
return (BOOL)(score < 2);
}];
This predicate defines a general predicate "template", which you can then use to filter the array with the actual string you're looking for:
NSDictionary<NSString *, id> *bindings = @{@"key": @"Nink"};
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa", nil];
NSIndexSet *indices = [array indexesOfObjectsPassingTest:^(id object, NSUInteger index, BOOL *stop) {
return [distancePredicate evaluateWithObject:object substitutionVariables:bindings];
}];
NSArray *results = [array objectsAtIndexes:indices];
BTW, there is nothing special about the word @"key"
; you can change that to be any string identifying the substitution (e.g. @"name"
, @"term"
, etc., are all valid). The key you provide in the substitution variables is the key you should use to retrieve the value.
Related Topics
How Secure Is Nsuserdefaults on iOS 8,9
iOS 11 Uitableview Delete Rows Animation Bug
iOS Static Framework with Resources Inside
Can't Find Pods.Modulemap - Looking in Wrong Directory
Watch Os 2.0 Beta: Access Heart Beat Rate
How to Apply Filter to Video Real-Time Using Swift
How to Stop Firebase from Logging Status Updates When App Is Launched
How to Change the Size of Uiactivityindicator
How to Detect Live Changes on Textfield in Swiftui
Accidentally Removed Xcassets File from Xcode Project
How to Cast an Nsmutablearray to a Swift Array of a Specific Type
How to Check Whether Dark Mode Is Enabled in iOS/Ipados
Swiftui: Unwanted Split View on iPad
How to Share Image in Instagramswift
Gcd VS Performselectorinbackground/Performselectoronmainthread
Issue with Auto Layout on iOS 8 (Code Works Perfectly on iOS 7)