Which Has Faster Performance Indexesofobjectspassingtest or Filteredarrayusingpredicate

Which has faster performance indexesOfObjectsPassingTest or filteredArrayUsingPredicate?

The following tests (compiled in Release mode, executed on a Mac Pro) indicate that
filteredArrayUsingPredicate is slower than indexesOfObjectsPassingTest if you use
a "textual" predicate, but faster if you use block-based predicate.
The fasted method in my test was a simple (fast-enumeration) loop that adds all matching
objects to a mutable array.

Results for filtering an array of 10,000,000 dictionaries, where about 50% match the predicate:


8.514334 (predicateWithFormat)
4.422550 (predicateWithBlock)
5.170086 (indexesOfObjectsPassingTest)
3.154015 (fast-enumeration + mutable array)

Of course the results may be different for other predicates.

#import <Foundation/Foundation.h>

NSUInteger filter1(NSArray *a)
{
NSPredicate *pred = [NSPredicate predicateWithFormat:@"num > 1000 AND foo == 'bar'"];
NSArray *filtered = [a filteredArrayUsingPredicate:pred];
return [filtered count];
}

NSUInteger filter2(NSArray *a)
{
NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *obj, NSDictionary *bindings) {
return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
}];
NSArray *filtered = [a filteredArrayUsingPredicate:pred];
return [filtered count];
}

NSUInteger filter3(NSArray *a)
{
NSIndexSet *matching = [a indexesOfObjectsPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
return ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]);
}];
NSArray *filtered = [a objectsAtIndexes:matching];
return [filtered count];
}

NSUInteger filter4(NSArray *a)
{
NSMutableArray *filtered = [NSMutableArray array];
for (NSDictionary *obj in a) {
if ([obj[@"num"] intValue] > 1000 && [obj[@"foo"] isEqualToString:@"bar"]) {
[filtered addObject:obj];
}
}
return [filtered count];
}

void testmethod(NSArray *a, NSUInteger(*method)(NSArray *a))
{
@autoreleasepool {
NSDate *t1 = [NSDate date];
NSUInteger count = method(a);
NSDate *t2 = [NSDate date];
NSLog(@"%f", [t2 timeIntervalSinceDate:t1]);
}
}

int main(int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray *a = [NSMutableArray array];
for (int i = 0; i < 10000000; i++) {
[a addObject:@{@"num": @(arc4random_uniform(2000)), @"foo":@"bar"}];
}
testmethod(a, filter1);
testmethod(a, filter2);
testmethod(a, filter3);
testmethod(a, filter4);
}
return 0;
}

iOS - searching in a large NSArray is slow

You should try to use the profiler to find the weakest line,
but I assume that the problem is that predicate block is evaluated for every entry every time.

I would suggest you to create your own wrapper class for ABRecordRef (let's say RecordWrapper), which will contain link to ABRecordRef with whole data and cache some frequent used and important values (e.g. fullName), you can obtain it once while loading list of contacts.

Then if you have an array of RecordWrapper* objects you can filter simply by calling

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"fullName contains[c] %@", searchText];
searchResults = [self.allContactsWrappers filteredArrayUsingPredicate:resultPredicate];

This should significantly increase filtering speed.

Predicate for range of NString in a Array

You could basically split the string and search for the array on the cityArry.

NSString *scannedStr = @"Chennai Tnager";

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF in[cd] %@", [scannedStr componentsSeparatedByString:@" "]];

[cityArray filteredArrayUsingPredicate: predicate];

isSubsetOfSet in NSPredicate string

Something like this should work:

NS(Ordered)Set *smallerSet = …
request.predicate =
[NSPredicate predicateWithFormat:@"SUBQUERY(attribute, $a, $a IN %@).@count == %lu",
smallerSet, (unsigned long)[smallerSet count]];

The predicate checks if the number of "attribute" values contained in smallerSet is
equal to the number of elements in smallerSet. If yes, then smallerSet must be
a subset of the "attribute" set.

A string based predicate is not generally faster than a block based (compare
https://stackoverflow.com/a/21158730/1187415). But a Core Data fetch request (with a
SQlite store file) cannot use block based predicates.

Efficient means to enumerate an array looking for items in another array

My thought would be to use a set -

-(NSArray*)getItemsWithGuids:(NSArray*)guids inAllObjects:(NSArray *)allObjects 
{

NSSet *matchGuids=[NSSet setWithArray:guids];
NSMutableArray *matchingObjects=[NSMutableArray new];
for (SOmeObjectWithGuidProperty *someObject in allObjects) {
if ([matchGuids contains:someObject.guid]) {
[matchingObjects addObject:someObject];
}
}

return [matchingObjects copy];
}

find number of yes in NSMutableArray

You can use NSPredicate

NSArray *totalYes = [carBoxesArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(isDeleted == %@)", @"yes"]];

NSLog(@"Found Total YES: %d",totalYes.count);

Objective-C: How to find the most common string in an array?

Simplest way is probably NSCountedSet:

NSCountedSet* stringSet = [[NSCountedSet alloc] initWithArray:strings];
NSString* mostCommon = nil;
NSUInteger highestCount = 0;

for(NSString* string in stringSet) {
NSUInteger count = [stringSet countForObject:string];
if(count > highestCount) {
highestCount = count;
mostCommon = string;
}
}

How to filter array based on dictionary key?

There are at least a half-dozen ways to do this. You don't say if you're using Objective-C or Swift, although the sample code you show looks like Objective-C.

If you were using Swift you could use the built-in Swift filter function, but let's forgo that.

You could use filteredArrayUsingPredicate, as you're doing now.

You could use indexesOfObjectsPassingTest to build an NSIndexSet of the objects in your array that meet your criteria (That method takes a block, and for all objects where your block returns true, the resulting index set includes the index of the object. You'd then use objectsAtIndexes to return an array of the objects listed in the index set.

I haven't benchmarked it, but I suspect that for large arrays, the predicate method is slower, since predicates are a very flexible method of selecting objects, and flexible code tends to be slower code. However, unless you are filtering tens of thousands of objects, or more, I doubt if you'd even notice the difference in performance.

Don't fall into the trap of premature optimization - wasting your time and making your code more complex to optimize things that do not have a meaningful impact on your app's performance.

Unless your app is running noticeably slowly, and you've tested it and determined that the array filtering has a significant influence on that slowness, it's probably not worth worrying about.



Related Topics



Leave a reply



Submit