сравнивая массивы в target-c - PullRequest
12 голосов
/ 16 июля 2009

Хорошо, довольно простой вопрос .. в c ++ это похоже на работу, но в target-c мне, кажется, приходится с этим бороться: Если вы хотите сравнить два массива, это должно быть примерно так

for ( int i = 0; i < [appdelegate.nicearray count]; i++ ) 
{ 
  if ( appdelegate.nicearray[i] == appdelegate.exercarray[i] )
  { 
     NSLog(@"the same elements in this selection");
  }
}

в чем конкретно проблема?

Ответы [ 5 ]

41 голосов
/ 16 июля 2009

Это объекты массива Какао (экземпляры NSArray), а не массивы C или векторы C ++, и помните, что Objective-C не имеет перегрузки операторов. Единственное, что вы можете делать с объектом, это передавать его, хранить в переменных и отправлять ему сообщения.

Таким образом, оператор массива-индекса не подходит для объектов Objective-C. Я не думаю, что даже лингвистически правильно разыменовывать указатель на объект Objective-C, поэтому этот код должен давать вам ошибку компилятора. Возможно, я не помню, хотя. Если это произойдет во время выполнения, этот код рано или поздно потерпит крах, так как вы обращаетесь к памяти за пределами объектов массива.

(РЕДАКТИРОВАТЬ с 2013 года: теперь Objective-C поддерживает подписку объектов. В конечном итоге это приводит к соответствующему сообщению objectAtIndex: или replaceObjectAtIndex:withObject:. Таким образом, код в вопросе фактически будет работать сейчас, хотя все еще не работает правильный способ просто пройти массив, а тем более сравнить два массива.)

Правильный способ получить объект из объекта NSArray по его индексу - это не использовать оператор массива-индекса, а отправить объекту массива сообщение objectAtIndex::

[myArray objectAtIndex:i]

Правильный способ итерации элементов массива, если вы действительно не нуждаетесь в индексе для чего-то другого (например, замена объектов в изменяемом массиве), состоит в том, чтобы зацикливаться на нем напрямую (это называется « быстрое перечисление »):

for (MyObject *myObject in myArray) {
    …
}

NSArray также отвечает на objectEnumerator и reverseObjectEnumerator, которые возвращают аналогично повторяемый объект. Из этих двух, reverseObjectEnumerator более полезен в новом коде, так как вы можете просто выполнить итерацию в массиве, чтобы выполнить итерацию вперед. Оба они были наиболее полезны до того, как существовало быстрое перечисление; этот код выглядел так:

NSEnumerator *myArrayEnum = [myArray objectEnumerator];
MyObject *myObject;
while ((myObject = [myArrayEnum nextObject])) {
    …
}

(Да, это задание в условии. Намеренно, отсюда и дополнительные (). Мы смело закодировали тогда, не так ли?)

Для того, что вы делаете, вы, скорее всего, захотите отправить одному из массивов сообщение isEqualToArray:, как предложил Виллихем Тотланд:

BOOL theyAreEqual = [myFirstArray isEqualToArray:mySecondArray];

Это позволит убедиться, что оба массива имеют одинаковую длину, а затем обойти их оба в режиме блокировки, отправив isEqual: каждой паре объектов. Он вернет YES, если каждое isEqual: сообщение вернулось YES; NO в противном случае. Массивы могут содержать разные объекты, но если каждая пара равна, сами массивы равны.

Это предполагает, что вы хотите равноправие объектов. Два отдельных объекта равны, если один из них отвечает YES, когда вы отправляете ему сообщение isEqual: и пропускаете другой объект. Если вы хотите сравнить идентификаторы объектов, то вам нужно самостоятельно выполнить цикл блокировки и использовать ==:

BOOL arraysContainTheSameObjects = YES;
NSEnumerator *otherEnum = [otherArray objectEnumerator];
for (MyObject *myObject in myArray) {
    if (myObject != [otherEnum nextObject]) {
        //We have found a pair of two different objects.
        arraysContainTheSameObjects = NO;
        break;
    }
}

Но это маловероятно. В большинстве случаев я хотел проверить равенство объектов, а не идентичность, поэтому isEqualToArray: - это то, что я хотел.

19 голосов
/ 16 июля 2009

Вы хотите метод isEqualToArray:. Как в:

if ([arrayOne isEqualToArray:arrayTwo]) {
  // Do something
}

Это будет рекурсивно сравнивать два массива, при этом преимущество состоит в том, что они не требуют излишней схемы и не требуют цикла.

1 голос
/ 12 февраля 2015

Вот один маленький, который я собрал на основе примера с наивысшим рейтингом. Это просто проверяет, что массивы содержат одинаковые значения, независимо от порядка и наличия дубликатов. Я в основном использую это для сравнения ключей двух словарей (которые часто возвращают свои массивы allKeys в различных порядках сортировки), чтобы увидеть, содержат ли они одни и те же объекты. Спасибо Питеру Хосли за предоставленный пример, из которого я адаптировал это.

#pragma mark - Arrays
// Check to see if arrays contain the same elements, not necessarily in the same order
// This is different from [array isEqualToArray:responseKeys] which demands the same order in both arrays
// ## Does not compensate for duplicate entries in an array
+ (BOOL)doArraysContainTheSameObjects:(NSArray *)firstArray withArray:(NSArray *)secondArray {
    BOOL arraysContainTheSameObjects = YES;

    for (id myObject in firstArray) {
        if (![secondArray containsObject:myObject]) {
            // We have found an object that is not in the other array.
            arraysContainTheSameObjects = NO;
            break;
        }
    }
    return arraysContainTheSameObjects;
}
1 голос
/ 16 июля 2009

Попробуйте сообщить нам результат, который вы получаете при запуске этого кода. Подход правильный, но попробуйте это:

for (int i =0; i< appdelegate.nicearray.count; i++)
{
    if ([[appdelegate objectAtIndex:i] isEqual: [appdelegate.exercarray objectAtIndex:i]])
    {
        NSLog(@"the same");
    }
}  
0 голосов
/ 16 июля 2009

При сравнении массивов я делаю следующее:

  • Проверьте, не равен ли один из массивов нулю, а другой нет
  • Проверьте, совпадают ли длины
  • Выполните итерацию (используя цикл for, как у вас) для каждого элемента, проверяя соответствующий элемент в другом массиве.

Для сравнения элементов вам нужно определить, что вы хотите считать "равными". Они равны только в том случае, если указатели в массиве равны, или они могут быть равны, если содержимое тоже одинаково.

В случае указателя вы можете использовать ==.

Для глубокого сравнения вам может понадобиться CompareTo или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...