Как переместить элемент в NSMutableArray?

#objective-c

#objective-c

Вопрос:

Я хочу переместить строковый элемент в начало списка.

 NSMutableArray animal = "cat", "lion", "dog", "tiger";
  

Как мне переместить dog в начало списка?

Ответ №1:

Вы бы удалили элемент и вставили его в нужное место:

 id tmp=[[animals objectAtIndex:2] retain];
[animals removeObjectAtIndex:2];
[animals insertObject:tmp atIndex:0];
[tmp release];
  

Вы должны сохранить объект или, когда вы сообщите массиву удалить его, он освободит объект.

Если вы не знаете индекс, вы могли бы сделать что-то вроде этого:

 NSMutableArray* animals = [NSMutableArray arrayWithObjects:@"cat", @"lion", @"dog", @"tiger",nil];

for (NSString* obj in [[animals copy] autorelease]) {
    if ([obj isEqualToString:@"dog"]) {
        NSString* tmp = [obj retain];
        [animals removeObject:tmp];
        [animals insertObject:tmp atIndex:0];
        break;
    }
}
  

Этот метод просмотрит весь ваш список и выполнит поиск «dog», и если он найдет, он удалит его из исходного списка и переместит в индекс 0.

Комментарии:

1. Вместо индекса возможен ли поиск по строке?

2. @HardCode да, для его поиска просто потребуется цикл. Я обновлю свой ответ, чтобы отразить это

3. С ARC (автоматическое управление ссылками) сохранение теперь не проблема. Он не должен быть выпущен, пока вы получили эту локальную переменную. (Я прав?)

4. @bluesm да, это правильно. на этот вопрос был дан ответ до того, как ARC был выпущен или стал стандартным.

5. @utahwithak Вы можете редактировать 🙂 И сэкономить время сотен разработчиков 🙂

Ответ №2:

Я хотел бы указать на неэффективность вашего метода. Удаляя / вставляя объект из NSMutableArray, вы потенциально влияете на каждую строку после удаления / вставки. Я говорю «потенциально», потому что неясно, какой внутренний метод Apple использует для поддержания своих изменяемых массивов. Однако, предполагая, что это простой c-массив, тогда каждую строку после этого индекса удаления / вставки необходимо будет перемещать вниз / вверх. В очень большом массиве это может быть неэффективно, если перемещаемые элементы находятся в начале. Однако замена элементов в массиве совсем не неэффективна. Таким образом, ниже приведена категория в NSMutableArray (обратите внимание, что этот код находится под ARC, поэтому управление памятью отсутствует):

 - (void) moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex{
    if (fromIndex == toIndex) return;
    if (fromIndex >= self.count) return; //there is no object to move, return
    if (toIndex >= self.count) toIndex = self.count - 1; //toIndex too large, assume a move to end
    id movingObject = [self objectAtIndex:fromIndex];

    if (fromIndex < toIndex){
        for (int i = fromIndex; i <= toIndex; i  ){
            [self replaceObjectAtIndex:i withObject:(i == toIndex) ? movingObject : [self objectAtIndex:i   1]];
        }
    } else {
        id cObject;
        id prevObject;
        for (int i = toIndex; i <= fromIndex; i  ){
            cObject = [self objectAtIndex:i];
            [self replaceObjectAtIndex:i withObject:(i == toIndex) ? movingObject : prevObject];
            prevObject = cObject;
        }
    }
}
  

Кроме того, небольшой бонус для дальнейшего расширения функциональности, если вы выполняете операции с перемещенными элементами (например, обновление базы данных или что-то в этом роде), следующий код был очень полезен для меня:

 - (void) moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex withBlock:(void (^)(id, NSUInteger))block{
    if (fromIndex == toIndex) return;
    if (fromIndex >= self.count) return; //there is no object to move, return
    if (toIndex >= self.count) toIndex = self.count - 1; //toIndex too large, assume a move to end
    id movingObject = [self objectAtIndex:fromIndex];
    id replacementObject;

    if (fromIndex < toIndex){
        for (int i = fromIndex; i <= toIndex; i  ){
            replacementObject = (i == toIndex) ? movingObject : [self objectAtIndex:i   1];
            [self replaceObjectAtIndex:i withObject:replacementObject];
            if (block) block(replacementObject, i);
        }
    } else {
        id cObject;
        id prevObject;
        for (int i = toIndex; i <= fromIndex; i  ){
            cObject = [self objectAtIndex:i];
            replacementObject = (i == toIndex) ? movingObject : prevObject;
            [self replaceObjectAtIndex:i withObject:replacementObject];
            prevObject = cObject;
            if (block) block(replacementObject, i);
        }
    }
}
  

Комментарии:

1. Метод выглядит как O (n), но должен быть O (1)

Ответ №3:

Вы можете удалить существующий элемент, например, dog, а затем снова вставить его в начало массива.

 NSMutableArray *animals = [NSMutableArray arrayWithObjects:@"cat", @"lion", @"dog", @"tiger",nil];
NSString *dog = @"dog";
// Check to see if dog is in animals
if ( [animals containsObject:dog] ) {
  // Remove dog from animals and reinsert
  // at the beginning of animals
  [animals removeObject:dog];
  [animals insertObject:dog atIndex:0];
}
  

Комментарии:

1. это выдает ошибку при AddObject. Ошибка: не найден возвращаемый тип по умолчанию равен id

2. Извините. Имя метода — insertObject:atIndex . У меня есть ядра для моего ответа