Shai Givati Shai Givati - 1 month ago 7
Objective-C Question

Reordering NSMutableArray by changing its starting index

Is there an efficient way to reorder NSMutableArray by changing its starting index? Example: if my array is [A,B,C,D,E], I would like to set 3rd element as starting element, and thus create the array [C,D,E,A,B].
I am doing it by slicing the array into two separate array, and then concatenating them. Is there a more efficient or clean way to do this?

Edit: the following is my current code

NSArray myArray = [self getMyArray]; // [A,B,C,D]
int startingIndex = 2;
NSArray *subArray1 = [myArray subarrayWithRange:NSMakeRange(_startingIndex, [myArray count] - _startingIndex + 1)]; // [C,D]
NSArray *subArray2 = [myArray subarrayWithRange:NSMakeRange(0, _startingIndex - 1)]; //[A,B]
NSMutableArray *reorderedArray = [NSMutableArray arrayWithArray:subArray1];
[reorderedArray addObjectsFromArray: subArray2]; //[C,D,A,B]

Answer

The most economical way of rotating NSMutableArray in terms of additional memory is the double-reversion algorithm described in this Q&A, because it does not require any additional storage. The idea is to reverse the entire array, and then reverse the two ranges separately.

In your example the array would be reversed, like this

E D C B A

then the first three elements would be reversed

C D E B A

and finally the tail of the array would be reversed:

C D E A B

Make a helper function for reversing a range, and call it three times:

reverseInPlace(myArray, 0, myArray.count-1);
reverseInPlace(myArray, 0, _startingIndex);
reverseInPlace(myArray, _startingIndex+1, myArray.count-1);

One way to implement reverseInPlace is as follows:

static void reverseInPlace(NSMutableArray *a, int f, int b) {
    while (f < b) {
        [a exchangeObjectAtIndex:f++ withObjectAtIndex:b--];
    }
}
Comments