HurkNburkS
HurkNburkS

Reputation: 5510

How to iterate over NSArray quickly

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

Answers (6)

T. Benjamin Larsen
T. Benjamin Larsen

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

Amin Negm-Awad
Amin Negm-Awad

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

Vizllx
Vizllx

Reputation: 9246

This is the most efficient approach

for (id object in array) {
    // do whatever you want
}

Upvotes: 1

Git.Coach
Git.Coach

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

Anoop Vaidya
Anoop Vaidya

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

Antonio MG
Antonio MG

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

Related Questions