Самый быстрый способ проверить, содержит ли массив те же объекты другого массива
Цель состоит в том, чтобы сравнить два массива как и проверить, содержат ли они одни и те же объекты (как можно быстрее - в массивах много объектов). Массивы не могут быть проверены с помощью 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;
}
Это работает, но это два вложенных быстрых перечисления. Есть ли способ сделать более быстрое сравнение?
Ответы
Ответ 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;