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?
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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With