Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimised array shift method

I have an NSMutableArray holding NSStrings e.g. {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

I would like to be able to shift elements with wrapping.

So e.g. move 1 to the centre, shifting all elements, wrapping the remaining ones (that cross the bounds) to the start again, and vice versa e.g. 10 to the centre.

{7, 8, 9, 10, 1, 2, 3, 4, 5, 6} and {6, 7, 8, 9, 10, 1, 2, 3, 4, 5}

Is there an optimised sort method like this already existing?

like image 469
some_id Avatar asked Jun 07 '13 10:06

some_id


2 Answers

The most efficient approach would be to create a wrapper object which maintains the current "origin" of the array and re-interprets indexes by adding that origin, modulo the length. In fact, if the array is only accessed in a handful of places this is easily done with 1-2 lines of code in-line.

-(id)objectForIndex:(NSInteger) index {
    NSInteger realIndex = (origin + index) % array.count;
    return [array objectAtIndex:realIndex];
}

(If this extends NS(Mutable)Array then "array" is "super". If only a wrapper then "array" is an instance var. "origin" is an instance var/property in either case.)

like image 146
Hot Licks Avatar answered Sep 21 '22 18:09

Hot Licks


I'm unaware of any methods on NSArray for this, but:

static NSArray *shiftArray(NSArray *array, NSInteger pos)
{
    NSInteger length = [array count];
    NSArray *post = [array subarrayWithRange:(NSRange){ .location = length - pos, .length = pos }];
    NSArray *pre = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - pos}];
    return [post arrayByAddingObjectsFromArray:pre];
}

e.g.:

NSArray *array = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I"];
NSLog(@"array = %@",shiftArray(array, 4));

Should do what you describe.

Logs to the console:

array = (
    F,
    G,
    H,
    I,
    A,
    B,
    C,
    D,
    E
)

Likely not performant.

like image 31
FluffulousChimp Avatar answered Sep 21 '22 18:09

FluffulousChimp