2013-06-07 11 views
5

Ich habe eine NSMutableArray halten NSStrings z. {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}Optimierte Array-Shift-Methode

Ich möchte Elemente mit Verpackung verschieben können.

Also z.B. bewege 1 zur Mitte, verschiebe alle Elemente und wickle die verbleibenden (die die Grenzen überschreiten) zum Anfang zurück und umgekehrt, z. 10 in die Mitte.

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

Gibt es eine optimierte sort Methode, wie dies bereits vorhanden?

+1

denke ich, dass wir, dass in der linearen Zeit mit einer 'for' Schleife tun kann, eine für die erste' k' Elemente sagen 1-6 und neben Rest 'm' Elemente, dh 7-10. und "k + m = n", was die Größe des Arrays ist. Aber ich kenne keinen Standardalgorithmus als solchen. –

+0

@PraveenS - 'trueIndex = (Offset + Index)% array.count'. Ich denke, das ist besser als lineare Zeit. –

Antwort

2

Der effizienteste Ansatz wäre, ein Wrapper-Objekt zu erstellen, das den aktuellen "Ursprung" des Arrays beibehält und Indizes neu interpretiert, indem er diesen Ursprung hinzufügt, modulo die Länge. In der Tat, wenn auf das Array nur an einer Handvoll von Orten zugegriffen wird, ist dies leicht mit 1-2 Zeilen Code in-line getan.

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

(Wenn diese NS erstreckt (Mutable) Array dann "Array" ist "super". Wenn nur ein Wrapper dann "array" var eine Instanz ist. "Ursprung" ist eine Instanz var/Eigenschaft in jedem Fall .)

+0

Smart, keine Notwendigkeit zu mutieren. – jarryd

+0

Modulo! Genius! –

0

sicher, wenn Sie durch N Elemente verschieben, die alles umwickeln müssen, was Sie tun würden, nehmen Sie die letzten N Array-Elemente und kleben sie an der Vorderseite?

und wenn Sie in die andere Richtung wechseln, nehmen Sie die Vorderseite und legen Sie sie auf die Rückseite.

2

Ich bin keine Kenntnis von Methoden auf NSArray für diese, aber:

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]; 
} 

z.B .:

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

Sollte das tun, was Sie beschreiben.

Logs an die Konsole:

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

wahrscheinlich nicht performant.

0

Drehen wird im Wesentlichen durchgeführt, indem N Elemente von einem Ende des Arrays genommen und stattdessen auf das andere Ende gelegt werden. Sie könnten dies mit unveränderlichen Arrays tun, wenn Sie möchten, aber veränderbare Arrays bieten eine etwas sauberere Implementierung.

Für links dreht, ist der einfachste Weg, wahrscheinlich nur:

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateLeft %= array.count; 

NSRange range = NSMakeRange(0, numberOfObjectsToRotateLeft); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

[rotatedArray addObjectsFromArray:[rotatedArray subarrayWithRange:range]]; 
[rotatedArray removeObjectsInRange:range]; 

// now return or use rotatedArray 

rechts dreht ähnlich wäre, aber der Bereich am Ende des Arrays sein würde, und Sie würden die Objekte einfügen an der Position index 0 mit -insertObjects:atIndexes::

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateRight %= array.count; 

NSRange range = NSMakeRange(array.count - numberOfObjectsToRotateRight, numberOfObjectsToRotateRight); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

NSArray * movedObjects = [rotatedArray subarrayWithRange:range]; 
[rotatedArray removeObjectsInRange:range]; 
[rotatedArray insertObjects:movedObjects atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfObjectsToRotateRight)]]; 

// now return or use rotatedArray 
1
-(NSArray*)shiftForward:(BOOL)forward withbits:(int)bit 
{ 
    NSInteger length = [array count]; 
    NSArray *right; 
    NSArray *left; 

    if (forward) { 
     //code for right shift 
     right = [array subarrayWithRange:(NSRange){ .location = length - bit, .length = bit }]; 
     left = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    }else{ 
     //code for left shift 
     left = [array subarrayWithRange:(NSRange){ .location =0, .length = bit }]; 
     right= [array subarrayWithRange:(NSRange){ .location = bit, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    } 
} 

- (void)viewDidLoad 
{ 
    array = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"]; 
    NSLog(@"array is %@",[self shiftForward:YES withbits:3]); 
} 
Verwandte Themen