Reputation: 5510
I have a method that iterates over an NSArray of NSDictionaries and changes values when an if statement is satisfied. However, for say 800 objects this can take 15-20 seconds.
I would like it to be much quicker and think maybe my logic could be improved. This is what I am doing:
// inside my method
for (int i = 0; i < [sortedItemsArray count]; i++) {
NSDictionary *tempInstForCopy = [sortedItemsArray objectAtIndex:i];
tempInstObjectDictionary = [tempInstForCopy mutableCopy];
tempInstForCopy = nil;
// show InsFitButton
if (([[tempInstObjectDictionary objectForKey:@"newIComp"] isEqualToString:@"T"]) && ([[tempInstObjectDictionary objectForKey:@"newJCom"] isEqualToString:@"W"])) {
// make changes in here. continue with the loop.
Upvotes: 1
Views: 295
Reputation: 6393
Speed optimizing is always "fun". Beware though the below tips might not help in your particular case and are designed for speed not readability. (Which is a big red flag).
In addition to the fast enumeration tips from Antonio MG and changing the dictionaries to Mutable earlier in the stack there are a few other steps you might look into:
If for instance you know that [[tempInstObjectDictionary objectForKey:@"newIComp"] isEqualToString:@"T"]
registers TRUE a lot more often than [[tempInstObjectDictionary objectForKey:@"newJCom"] isEqualToString:@"W"]
(or vice versa) you could save some cycles nesting the two ifs*, checking first at the rarest case:
if ([[tempInstObjectDictionary objectForKey:@"newJCom"] isEqualToString:@"W"]){
if ([[tempInstObjectDictionary objectForKey:@"newIComp"] isEqualToString:@"T"]){
// make changes in here. continue with the loop.
}
}
Also, depending on your design and what you are trying to achieve, you might improver performance by adding the dictionaries you need to change to a new array, and alter them on another thread after you've finished your loop...
*Actually I'm not sure if you even need to nest them, switching the order might achieve the same thing(?) Any compiler-experts feel free to chime in...
Upvotes: 0
Reputation: 16660
Beside the answers to make the loop itself faster, I agree that the loop is not your problem, but what you do inside the loop.
Before changing the items into mutable dictionary I would use a custom class.
On a first view there are two problems:
You create a mutable copy for every item. Object creation is potentially slow.
You have to insert the changed copy into the array again, don't you?
Both operations would be less expensive, if you have instances of a custom class (or of mutable dictionary). Without changing the type of the items, it would improve the runtime behavior, if you create the mutable copy (tempInstObjectDictionary
) only inside the if
, so it is only created when it is needed.
Upvotes: 0
Reputation: 9246
This is the most efficient approach
for (id object in array) {
// do whatever you want
}
Upvotes: 1
Reputation: 3092
By iterating quickly I guess that you’re talking about the runtime of this loop right? For your example it would be faster if you wouldn’t have to create a copy of the dictionary every time. Try changing them into NSMutableDictionary
types
When iterating through this array are there any cases where you can shorten the process? If you changed a value, do you have to continue the loop or can you break;
(and maybe save the current index and continue when needed)?
I don’t know your exact problem, but oftentimes it’s possible to split up big arrays like this in smaller subarrays which you can target better.
Upvotes: 0
Reputation: 46563
You can use fast enumeration for all the collection classes and its subclasses:
for (<objectType> objectName in <collectionObject>{
...
}
Note: You can't change/update the objectName in fast enumeration as it becomes constant.
Upvotes: 1
Reputation: 20410
Try fast enumeration:
for (NSDictionary *tempInstForCopy in sortedItemsArray) {
}
Also, maybe you don't need to make copies of every dictionary for every entry, you can store then as mutable from the beggining.
Upvotes: 4