Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 387 Vote(s) - 3.47 Average
  • 1
  • 2
  • 3
  • 4
  • 5
filtering NSArray into a new NSArray in Objective-C

#1
I have an `NSArray` and I'd like to create a new `NSArray` with objects from the original array that meet certain criteria. The criteria is decided by a function that returns a `BOOL`.

I can create an `NSMutableArray`, iterate through the source array and copy over the objects that the filter function accepts and then create an immutable version of it.

Is there a better way?
Reply

#2
Assuming that your objects are all of a similar type you could add a method as a category of their base class that calls the function you're using for your criteria. Then create an NSPredicate object that refers to that method.

In some category define your method that uses your function

@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
return someComparisonFunction(self, whatever);
}
@end

Then wherever you'll be filtering:

- (NSArray *)myFilteredObjects {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
return [myArray filteredArrayUsingPredicate:pred];
}

Of course, if your function only compares against properties reachable from within your class it may just be easier to convert the function's conditions to a predicate string.
Reply

#3
Based on an answer by Clay Bridges, here is an example of filtering using blocks (change `yourArray` to your array variable name and `testFunc` to the name of your testing function):

yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [self testFunc:obj];
}]];
Reply

#4
`NSPredicate` is nextstep's way of constructing condition to filter a collection (`NSArray`, `NSSet`, `NSDictionary`).

For example consider two arrays `arr` and `filteredarr`:

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

filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

the filteredarr will surely have the items that contains the character c alone.

to make it easy to remember those who little sql background it is

*--select * from tbl where column1 like '%a%'--*

**1)select * from tbl** --> collection

**2)column1 like '%a%'** --> `NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];`

**3)select * from tbl where column1 like '%a%'** -->

[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

I hope this helps
Reply

#5
If you are OS X 10.6/iOS 4.0 or later, you're probably better off with blocks than NSPredicate. See [`-[NSArray indexesOfObjectsPassingTest:]`][0] or write your own category to add a handy `-select:` or `-filter:` method ([example][1]).

Want somebody else to write that category, test it, etc.? Check out [BlocksKit][2] ([array docs][3]). And there are __many__ more examples to be found by, say, searching for e.g. ["nsarray block category select"][4].


[0]:

[To see links please register here]

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]: http://www.google.com/search?client=safa...p;oe=UTF-8
Reply

#6
Checkout this library

[To see links please register here]


It comes with lots of easy array functions to never write a loop again

So you can just do:

NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];

or

NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
return object.age.intValue < 20;
}];
Reply

#7
`NSArray` and `NSMutableArray` provide methods to filter array contents. `NSArray` provides **filteredArrayUsingPredicate:** which returns a new array containing objects in the receiver that match the specified predicate. `NSMutableArray` adds **filterUsingPredicate:** which evaluates the receiver’s content against the specified predicate and leaves only objects that match. These methods are illustrated in the following example.

NSMutableArray *array =
[NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];

NSPredicate *bPredicate =
[NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
[array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.

NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }
Reply

#8
The Best and easy Way is to create this method And Pass Array And Value:

- (NSArray *) filter:(NSArray *)array where:(NSString *)key is:(id)value{
NSMutableArray *temArr=[[NSMutableArray alloc] init];
for(NSDictionary *dic in self)
if([dic[key] isEqual:value])
[temArr addObject:dic];
return temArr;
}
Reply

#9
Another category method you could use:

- (NSArray *) filteredArrayUsingBlock:(BOOL (^)(id obj))block {
NSIndexSet *const filteredIndexes = [self indexesOfObjectsPassingTest:^BOOL (id _Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
return block(obj);
}];

return [self objectsAtIndexes:filteredIndexes];
}

Reply

#10
There are loads of ways to do this, but by far the neatest is surely using `[NSPredicate predicateWithBlock:]`:


NSArray *filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object shouldIKeepYou]; // Return YES for each object you want in filteredArray.
}]];

I think that's about as concise as it gets.


----------
## Swift:

For those working with `NSArray`s in Swift, you may prefer this _even more_ concise version:

let filteredArray = array.filter { $0.shouldIKeepYou() }

`filter` is just a method on `Array` (`NSArray` is implicitly bridged to Swift’s `Array`). It takes one argument: a closure that takes one object in the array and returns a `Bool`. In your closure, just return `true` for any objects you want in the filtered array.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through