#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 . У меня есть ядра для моего ответа