Подтвердить что ты не робот

Самый быстрый способ проверить, содержит ли массив те же объекты другого массива

Цель состоит в том, чтобы сравнить два массива как и проверить, содержат ли они одни и те же объекты (как можно быстрее - в массивах много объектов). Массивы не могут быть проверены с помощью isEqual:, поскольку они по-разному сортируются.

Я уже пробовал решение, размещенное здесь (qaru.site/info/290226/... - см. последний фрагмент кода сообщения Peter Hosey). Но это не работает с по-разному отсортированными массивами.

Код, который я использую сейчас, следующий:

+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 {
    // quit if array count is different
    if ([array1 count] != [array2 count]) return NO;

    BOOL bothArraysContainTheSameObjects = YES;
    for (id objectInArray1 in array1) {
        BOOL objectFoundInArray2 = NO;
        for (id objectInArray2 in array2) {
            if ([objectInArray1 isEqual:objectInArray2]) {
                objectFoundInArray2 = YES;
                break;
            }
        }
        if (!objectFoundInArray2) {
            bothArraysContainTheSameObjects = NO;
            break;
        }
    }

    return bothArraysContainTheSameObjects;
}

Это работает, но это два вложенных быстрых перечисления. Есть ли способ сделать более быстрое сравнение?

4b9b3361

Ответ 1

В соответствии с вашим кодом вы строго придерживаетесь одинакового количества элементов, и каждый объект первого массива должен находиться во втором массиве и наоборот.

Самый быстрый способ - отсортировать оба массива и сравнить их.

Пример:

NSArray *[email protected][@"a",@"b",@"c"];
NSArray *[email protected][@"c",@"b",@"a"];

array1=[array1 sortedArrayUsingSelector:@selector(compare:)];
array2=[array2 sortedArrayUsingSelector:@selector(compare:)];

if ([array1 isEqualToArray:array2]) {
    NSLog(@"both have same elements");
}
else{
    NSLog(@"both having different elements");
}

Ответ 2

Как преобразовать оба массива в множество и сравнить их.

NSSet *set1 = [NSSet setWithArray:arr1];
NSSet *set2 = [NSSet setWithArray:arr2];

Сравните два, используя

if([set1 isEqualToSet:set2]) {

}

Ответ 3

Используйте метод containsObject: вместо повторения всего массива.

NSArray *array;
array = [NSArray arrayWithObjects: @"Nicola", @"Margherita",                                       @"Luciano", @"Silvia", nil];
if ([array containsObject: @"Nicola"]) // YES
  {
    // Do something
  }

как это

+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 {
    // quit if array count is different
    if ([array1 count] != [array2 count]) return NO;

    BOOL bothArraysContainTheSameObjects = YES;

    for (id objectInArray1 in array1) {

        if (![array2 containsObject:objectInArray1])
        {
            bothArraysContainTheSameObjects = NO;
            break;
        }

    }

    return bothArraysContainTheSameObjects;
}

Ответ 4

Если вы хотите проверить, содержат ли оба массива одинаковые дубликаты, просто используйте NSCountedSet. Это похоже на NSSet, но каждый объект в наборе также имеет счет, рассказывающий вам, как часто он был добавлен. Так

BOOL same = (array1.count == array2.count);
if (same && array.count > 0)
{
    NSCountedSet* set1 = [[NSCountedSet alloc] initWithArray:array1];
    NSCountedSet* set2 = [[NSCountedSet alloc] initWithArray:array2];
    same = ([set1 isEqual: set2]);
}

Независимо от того, как вы это сделаете, это потребует много времени, поэтому вы можете подумать, есть ли особые случаи, с которыми можно справиться быстрее. Являются ли эти массивы обычно одинаковыми или почти одинаковыми, или это правда в 99% случаев, когда они различны и что 99% времени случайный элемент массива1 не находится в массиве2? Часто ли отсортированы массивы? В этом случае вы можете проверить, есть ли одинаковые объекты в одинаковых позициях, а затем учитывать только те объекты, которые не совпадают. Если один массив содержит объекты a, b, c, d, e, а другой содержит a, b, x, d, y, вам нужно сравнить массив [c, e] vs. [x, y].

Ответ 5

Пытался принять принятый ответ, но это было не совсем хорошо для моей ситуации.

Я нашел этот ответ, и все кредиты для @joel kravets для метода.

В основном сортировка с использованием компаратора позволяет вам легче сортировать объекты, поэтому проблема, с которой я столкнулся при попытке использовать вышеупомянутое решение.

NSArray * array1 = [NSArray arrayWithArray:users];
NSArray * array2 = [NSArray arrayWithArray:threadUsers];

id mySort = ^(BUser * user1, BUser * user2){
    return [user1.name compare:user2.name];
};

array1 = [array1 sortedArrayUsingComparator:mySort];
array2 = [array2 sortedArrayUsingComparator:mySort];

if ([array1 isEqualToArray:array2]) {
    NSLog(@"both are same");
}
else{
    NSLog(@"both are different");
}

Раньше я пытался использовать другие ответы, подобные приведенным выше, используя break для прохождения циклов, но в конце концов этот ответ вышел проще всего из-за его скорости, а также, что в конце концов мы имеем оператор if, позволяющий нам кода в зависимости от того, являются ли они одинаковыми или разными.

Спасибо Anoop за то, что он меня на правильном пути, и Джоэл за то, что помог мне усилить его эффективность

Ответ 6

Таким образом, сложность O (N ^ 2), если вы будете следовать этому подходу, вы не сможете сделать это с меньшей сложностью. Вместо этого вы можете сделать это с помощью O (N log (N)), если сортировать оба массива и затем сравнивать их. Таким образом, после их сортировки вы сделаете это, используя isEqualToArray: в других N операциях.

Ответ 7

[docTypes containsObject:@"Object"];

Он будет работать для вашего req. Еще быстрее он вернет логическое значение для него.

Ответ 8

NSArray *filtered = [someArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"someParamter == %@", paramValue]]];
if (filtered.count) {

}

Основной плюс вы можете использовать его для любых объектов: custom, system, NSDictionary. например, мне нужно знать, что мой стек UINavigationController содержит MySearchResultsVC и MyTopMenuItemsVC или нет:

    NSArray *filtered = [self.navigationController.viewControllers filteredArrayUsingPredicate:
                                     [NSPredicate predicateWithFormat:@"class IN %@",
                                      [NSArray arrayWithObjects:
                                       [MySearchResultsVC class],
                                       [MyTopMenuItemsVC class],
                                       nil]]];
if (filtered) {
/* ok, now we can handle it! */
}

Ответ 9

Я знаю это поздно, но я просто хочу поделиться тем, что я сделал.

NSString *stringArr1 = [NSString stringWithFormat:@"%@", array1];
NSString *stringArr2 = [NSString stringWithFormat:@"%@", array2];

if ([stringArr1 isEqual: stringArr2])
    NSLog(@"identical");
else
    NSLog(@"not");

это похоже на сравнение "@[@1, @2, @3, @4]" == "[@3, @2, @1, @4]" . что, очевидно, неверно.

Ответ 10

Я думаю, это будет делать:

[array1 isEqualToArray:array2];

возвращает bool;