Find indexOfObject from NSArray - objective-c

I have an NSArray filled with custom objects.
Each object has several variables: pk, amount, date etc..
I want to fetch the object that has the highest number in the pk variable.
I can do this using:
NSUInteger maximumpk = [[bets valueForKeyPath:#"#max.pk"] intValue];
This gives me the actual value from the highest pk. Now I need to get the index for that object. I have seen indexOfObject used when the array has just 1 variable of data, but how do I use it in this instance?
Thanks

Use -indexOfObjectPassingTest:, for example:
NSUInteger idx = [bets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return [obj pk] == maximumpk;
}];

Related

Objective C NSMutableDictionary

I have a question about NSMutableDictionary,
Let's say I have two set of NSMutableDictionary:
NSMutableDictionary *oddNumber
NSMutableDictionary *randomNumber
Is there a function to check value of randomNumber is SUBSET of value of oddNumber or not?
You can do something like this,
NSMutableDictionary *oddNumber;
NSMutableDictionary *randomNumber;
// Create arrays
NSArray *arroddNumber = [oddNumber allValues];
NSArray *arrrandomNumber = [oddNumber allValues];
// Turn the arrays into sets and intersect the two sets
NSMutableSet *oddNumberSet = [NSMutableSet setWithArray:arroddNumber];
NSMutableSet *randomNumbersSet = [NSMutableSet setWithArray:arrrandomNumber];
[oddNumberSet intersectSet:randomNumbersSet];
// The Values present in both arrays
NSLog(#"Common Values : %#", oddNumberSet);
You could get the values for each dictionary using the values method. This returns an array. You could then convert these arrays to sets, which have methods to check if one set is a subset of another.
Look at the values that you have. Make sure they have an isEqual: method and a hash method, so you can add them to a set. Create an NSSet with all values of the second dictionary, then iterate through the first dictionary and check which values are in the set.
Note that creating a set with N values takes O (N) time if the values have a decent hash function, and looking up a value in a set is constant time.
Short:
BOOL isSubset = [[oddNumber dictionaryWithValuesForKeys:[randomNumber allKeys]] isEqualToDictionary:randomNumber]
or faster:
__block BOOL isSubset = YES;
[randomNumber enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
id value = [oddNumber objectForKey:key];
if (!value || ![value isEqual:obj]) {
isSubset = NO;
*stop = YES;
}
}];

Objective-c: find the last index of an element in a NSArray

I have a NSArray, and I want to find the last occurrence of an element.
For example:
[apple, oranges, pears, apple, bananas];
int i = lastIndexOf("apple");
out: i == 3;
I'm struggling to find a simple solution looking an the APIS, but there aren't example so it's pretty hard to understand which function I should use.
NSUInteger index = [array indexOfObjectWithOptions:NSEnumerationReverse
passingTest:^(id obj, NSUInteger i, BOOL *stop) {
return [#"apples" isEqualToString:obj];
}];
If the array doesn't contain #"apples", index will be NSNotFound.
NSArray has indexOfObjectWithOptions:passingTest:, this will allow you to search in reverse.
For example:
NSArray *myArr = #[#"apple", #"oranges", #"pears", #"apple", #"bananas"];
NSString *target = #"apple";
NSUInteger index = [myArr indexOfObjectWithOptions:NSEnumerationReverse
passingTest:^BOOL(NSString *obj, NSUInteger idx, BOOL *stop) {
return [target isEqualToString:obj];
}];
You can find out more details of this method in the Documentation by Apple.
If anyone wants a reusable method with categories, I had written one for lastIndexOf.
Code can be found and freely used from here -
http://www.tejasshirodkar.com/blog/2013/06/nsarray-lastindexof-nsmutablearray-lastindexof/

get objects from NSMutable array with condition objective-c

I want to get some objects from array contains objects where one of objects property satisfy the condition
Like in c#
example :
NSMutablearray * coursesinfo ;
this array contain more than 30 courses
course is object on of its property is finalgrade
i want to get all courses where final grade < 100
can i do this in objective -c like c# ? and how?
the where statement is like using a predicate in cocoa/cocoa touch. here is an example, where I have an array of image file names from a directory and I am looking for the base file name. The indexesOfObjectsWithOptions: method returns a set of Indices that pass the specific test. NSEnumerationConcurrent utilizes a concurrent queue to take advantage of multiple cores, if present.
NSIndexSet *indexSet=[allImageURLs indexesOfObjectsWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
BOOL match=NO;
NSRange twoXRange=[((NSURL *)obj).absoluteString rangeOfString:#"#2x"];
NSRange iPhoneRange=[((NSURL *)obj).absoluteString rangeOfString:#"~ipad"];
if (twoXRange.location==NSNotFound && iPhoneRange.location==NSNotFound) {
match=YES;
}
return match;
}];
self.imageURLs=[allImageURLs objectsAtIndexes: indexSet];
for your particular case I would do the following:
NSIndexSet *theSet=[coursesinfo indexesOfObjectsWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
BOOL match=NO;
if( obj.finalGrade<100 ){
match=YES;
}
return match;
}];
NSArray *courses=[coursesinfo objectsAtIndexes: theSet];
Good luck!
t
The closest is use - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate function of NSArray.
Link to NSPredicate documentation.

Get NSMutableArray index depending on an object's property?

I'm currently trying to get hold of my NSMutableArray's index depending on one of it's object's properties.
I have an xml-structure such as this:
<timeperiod>
<Day>
<Date>20120325</Date>
</Day>
<Day>
<Date>20120326</Date>
</Day>
</timeperiod>
Now, imagine that the xml-structure contains every day in a month.
Day and all of it's properties are added to an NSMutableArray.
And what i want is: To get the array's index depending on the date.
I'm imagining something like this in pseudo-code:
-(NSInteger)getIndexFromObjectProperty:(NSString *)property{
// Givf index from array where date is for example 20120310
//pseudo
Return [myClassObject.ObjectArray indexFromProperty:property];
}
I found this: Sorting NSMutableArray By Object's Property
This sorts from properties, but how to get an index from a property 0_0
I also found this: Function to get index from an array of objects having certain value of provided property
Which would help alot if the syntax worked out of the box :(
Any tips and/or pointers will be highly appreciated.
Thanks in advance.
EDIT I'm currently trying the answers given. Will get back with an update.
EDIT2: Office is throwing me out since they're locking the building down... i'll get back to you tomorrow..
You can use indexOfObjectPassingTest: method to test each object with a block returning a BOOL.
-(NSInteger)getIndexFromObjectProperty:(NSString *)property{
return [myArray indexOfObjectPassingTest:
^(id obj, NSUInteger idx, BOOL *stop) {
// Return true if obj has the date that you are looking for.
BOOL res;
if ([property isEqualTo:[obj dateProperty]]) {
res = YES;
*stop = YES;
} else {
res = NO;
}
return res;
}];
}
This really was not as hard as i thought it would be..
solved by doing the following...
-(NSInteger)returnIndexFromDateProperty:(NSString *)property{
NSInteger iIndex;
for (int i = 0; i < [myArray count]; i++){
if([property isEqualToString:[[myArray objectAtIndex:i]dateProperty]]){
iIndex = i;
}
}
return iIndex;
}
Thanks for all the other answers. They hepled alot during the process of thinking (not being bad).
You can use
- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
I'm not sure how your date format is, but as I understood it's an NSString, so I'd do it like this :
-(NSInteger)indexFromDate:(NSString *)date{
return [myClassObject.ObjectArray indexOfObjectPassingTest:
^(id obj, NSUInteger idx, BOOL *stop) {
return ([obj isEqualToString:myIdentifier]);
}];
}
You can do this with NSPredicate
[array indexOfObject:[[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF.date == %#",date]] objectAtIndex:0]]
It's not clear from your post what structure your array will have after putting the XML data into it. Will it be an array of arrays? An array of dictionaries? Generally, to get an object from an array you use indexOfObject: or one of its variations.

How to remove elements in NSMutableArray or NSMutableDictionary during enumeration?

I am using block based enumeration similar to the following code:
[[[rows objectForKey:self.company.coaTypeCode] objectForKey:statementType]
enumerateObjectsWithOptions:NSEnumerationConcurrent
usingBlock:^(id coaItem, NSUInteger idx, BOOL *stop) {
// block code here
}]
I would like to remove some of the objects during the enumeration process depending on the their object values.
How could I do this? I know that manipulating an mutable array or dictionary (NSMutableArray or NSMutableDictionary) during enumeration is usually not possible.
What would be the best way to implement this?
Thank you!
Since you can't remove objects from an array or dictionary during enumeration, you'll have to accumulate the items you want to delete, and then delete them all after the enumeration.
If you're dealing with an array, you can just accumulate the indices.:
NSMutableIndexSet *indexesToDelete = [NSMutableIndexSet indexSet];
NSUInteger currentIndex = 0;
for (id obj in yourArray) {
//do stuff with obj
if (shouldBeDeleted(obj)) {
[indexesToDelete addIndex:currentIndex];
}
currentIndex++;
}
[yourArray removeObjectsAtIndexes:indexesToDelete];
Since the order of the keys in an NSDictionary is undefined, for an NSMutableDictionary you'll have to accumulate keys instead:
NSMutableArray *keysToDelete = [NSMutableArray array];
for (id obj in [yourDictionary keyEnumerator]) {
//do stuff with obj
if (shouldBeDeleted(obj)) {
[keysToDelete addObject:obj];
}
}
[yourDictionary removeObjectsForKeys:keysToDelete];
It's the same thing if you're enumerating with a block. Declare the enumerator in the same scope where you declare the block and it will be retained and just work.
Also worth looking at this question from 3 years ago: Best way to remove from NSMutableArray while iterating?.
Whether you build up an index set during enumeration, or modify the array itself during enumeration, you will have to give up NSEnumerationConcurrent, because most Cocoa objects cannot safely be modified simultaneously from multiple threads.
Anyway, the simplest (but maybe not most efficient) approach is to just enumerate a copy of the container.
For an array, you can enumerate a copy in reverse. I assume that as each item is being enumerated, you may decide to remove that item, but not other items previously enumerated or yet to be enumerated.
NSMutableArray *array = [[rows objectForKey:self.company.coaTypeCode] objectForKey:statementType];
[[array copy] enumerateObjectsWithOptions: NSEnumerationReverse
usingBlock:^(id coaItem, NSUInteger idx, BOOL *stop) {
if ([self objectIsTooUglyToExist:coaItem])
[array removeObjectAtIndex:idx];
}]
You have to enumerate the array in reverse to avoid changing the not-yet-enumerated part of the array.
For a dictionary, you can just enumerate a copy with no special options:
NSMutableDictionary *dictionary = someDictionary;
[[dictionary copy] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([self object:obj isTooUglyToExistAtKey:key])
[dictionary removeObjectForKey:key];
}];
Another option, with an array, is to use a conventional for loop, with the array's count as the limit. Then one needs to be cognizant of whether an element is removed from a location <= the index (in which case the index should be decremented) or > than the index (in which case the index is left unmodified other than the for statement's increment).
For a dictionary you can first create an array with allKeys, and then iterate through the array. In this case no fiddling with index values is required.