4

I know we could just use a NSMutableArray for the object, but what if that's not an option and we need to add new elements to an NSArray. How would we go about doing this?

My immediate answer would be to create a NSMutableArray with the original NSArray, add the new elements to it, then cast the NSMutableArray back to the original NSArray.

I was asked this in an interview and am curious what a correct solution might be, besides just use a NSMutableArray in the first place.

0

5 Answers 5

11
NSArray *array = [NSArray arrayWithObjects:@"One", @"Two", nil];

array = [array arrayByAddingObject:@"Three"];

or

NSArray *newArray = [NSArray arrayWithObjects:@"Three", @"Four", nil];

array = [array arrayByAddingObjectsFromArray:newArray];
Sign up to request clarification or add additional context in comments.

3 Comments

Let's suppose I have a very large array. What would be the most efficient way of doing what OP asks? Your solution, or the mutableCopy->add->cast solution proposed by OP?
Most efficient. Mutable array. Then the array by adding in my method. i dunno though. Test it and let me know your findings :-)
I tested this and they turned out to be the same as long as you're only adding one more element, regardless of the size. Here's the long explanation: stackoverflow.com/a/26517217/1564332
3

You can use mutableCopy on your NSArray object to return an NSMutableArray containing the previous objects.

Comments

3

NSArray objects are immutable so they cannot be modified. The only option is to create a new NSArray (via an intermediate NSMutableArray object perhaps) and put this new array back into the owning object (if it allows it).

Comments

1

I was wondering what the performance difference would be between using arrayByAddingObject and creating a mutable copy and then adding one element.

I found that it doesn't matter.

Here's what I used

- (IBAction)doTest
{
    for(int n = 0; n < 7; n++){
        [self runTestWithExponent:n];
    }
    NSLog(@"done");
}

- (void)runTestWithExponent:(double)exponent
{
    int arraySize = pow(10.0, exponent);

    NSMutableArray *originalMutableArray = [NSMutableArray arrayWithCapacity:arraySize];
    for(int i = 0; i < arraySize; i++){
        [originalMutableArray addObject:@(i)];
    }
    NSArray *originalArray = [NSArray arrayWithArray:originalMutableArray];
    originalMutableArray = nil;

    //test first time
    NSDate *now = [NSDate date];
    NSArray *newArray = [originalArray arrayByAddingObject:@(-1)];
    NSTimeInterval time1 = [[NSDate date] timeIntervalSinceDate:now];
    newArray = nil;

    //test second time
    now = [NSDate date];
    NSMutableArray *mutable = [originalArray mutableCopy];
    [mutable addObject:@(-1)];
    NSTimeInterval time2 = [[NSDate date] timeIntervalSinceDate:now];
    mutable = nil;

    NSString *winner = (time1 == time2) ? @"same" : ((time1 < time2) ? @"arrayByAdding" : @"mutable");
    NSLog(@"%i : %f --- %f : %@ %f%%", arraySize, time1, time2, winner, (time1/time2 * 100));
}

As you can see, I test different array sizes. Sizes of 1, 10, 100 ... 1,000,000. I found regardless of size, the times are very similar to each other. For any given length, sometimes one method is faster, and others, the other. I'm guessing internally they do the same thing.

Here's the output of three runs:

1 : 0.000026 --- 0.000034 : arrayByAdding 76.491228%
10 : 0.000011 --- 0.000011 : same 100.000000%
100 : 0.000021 --- 0.000024 : arrayByAdding 87.344913%
1000 : 0.000228 --- 0.000260 : arrayByAdding 87.689133%
10000 : 0.001458 --- 0.001406 : mutable 103.696638%
100000 : 0.015396 --- 0.015625 : arrayByAdding 98.534393%
1000000 : 0.158018 --- 0.162849 : arrayByAdding 97.033438%
done
1 : 0.000011 --- 0.000012 : arrayByAdding 92.039801%
10 : 0.000012 --- 0.000014 : arrayByAdding 85.531915%
100 : 0.000020 --- 0.000025 : arrayByAdding 79.952267%
1000 : 0.000185 --- 0.000144 : mutable 128.435430%
10000 : 0.001397 --- 0.001437 : arrayByAdding 97.216807%
100000 : 0.014448 --- 0.014132 : mutable 102.235803%
1000000 : 0.145622 --- 0.149862 : arrayByAdding 97.170746%
done
1 : 0.000013 --- 0.000012 : mutable 107.920792%
10 : 0.000011 --- 0.000013 : arrayByAdding 84.862385%
100 : 0.000025 --- 0.000029 : arrayByAdding 86.036961%
1000 : 0.000165 --- 0.000135 : mutable 122.207506%
10000 : 0.001547 --- 0.001470 : mutable 105.242884%
100000 : 0.014817 --- 0.014337 : mutable 103.347954%
1000000 : 0.146554 --- 0.148468 : arrayByAdding 98.710857%
done

Keep in mind that this was only tested for adding one element. I suspect that (for example) adding 500 elements to the 1,000 sized array will probably be faster using the second method, but I leave such experiments to someone else.

Comments

0

This is simply a trick question. NSArrays are immutable and cannot be altered without creating a new NSArray or NSMutableArray from the previous array, plain and simple.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.