У меня два массива, но они разной длины . Я хочу сравнить эти два массива и поместить общие элементы в новый массив . при этом не должно быть дубликатов элементов - это третий массив. Я действительно напортачил с этим, пожалуйста, помогите мне. очень благодарен. . .
3 ответа
Что-то вроде этого?
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets
NSArray* result = [set1 allObjects];
Это дает то преимущество, что не ищет объекты в массиве при циклическом просмотре другого массива, который имеет сложность N ^ 2 и может занять некоторое время, если массивы большие.
Изменить: set2 не обязательно должен быть изменяемым, с тем же успехом можно использовать только
NSSet* set2 = [NSSet setWithArray:array2];
Третий подход (помимо использования наборов или простого цикла, проверяющего каждый элемент с помощью contains) заключался бы в сортировке обоих массивов, а затем использовании двух индексов:
// approach using sets:
NSArray *arrayUsingSets(NSMutableArray *arr1, NSMutableArray *arr2)
{
NSMutableSet *set1 = [NSMutableSet setWithArray: arr1];
NSSet *set2 = [NSSet setWithArray: arr2];
[set1 intersectSet: set2];
return [set1 allObjects];
}
// my approach:
NSArray *arrayUsingComp(NSMutableArray *arr1, NSMutableArray *arr2)
{
NSMutableArray *results = [NSMutableArray arrayWithCapacity: arr1.count + arr2.count];
// Assumes input arrays are sorted. If not, uncomment following two lines.
// [arr1 sortUsingSelector: @selector(compare:)];
// [arr2 sortUsingSelector: @selector(compare:)];
int i = 0;
int j = 0;
while ((i < arr1.count) && (j < arr2.count))
{
switch ([[arr1 objectAtIndex: i] compare: [arr2 objectAtIndex: j]])
{
case NSOrderedSame:
[results addObject: [arr1 objectAtIndex: i]];
i++, j++;
break;
case NSOrderedAscending:
i++;
break;
case NSOrderedDescending:
j++;
break;
}
}
// NOTE: results are sorted too.
// NOTE 2: loop must go "backward".
for (NSInteger k = results.count - 1; k > 0; k--)
if ([[results objectAtIndex: k] isEqual: [results objectAtIndex: k-1]])
[results removeObjectAtIndex: k];
return results;
}
Я провел простое профилирование, и если я создаю изменяемые копии переданных массивов и сортирую их, он работает в 1,5 раза медленнее , чем подход с использованием наборов. Мой подход, описанный выше, кажется, работает в 1,5 раза быстрее , чем подход с использованием наборов. Если гарантировано, что массивы уже отсортированы, мой подход будет работать еще лучше ( почти в 4 раза быстрее , чем версия, использующая наборы), поскольку сортировка не требуется.
Обновить:
Это не устранило дубликаты, поэтому я добавил цикл в конце процедуры. Сейчас это всего в 3 раза быстрее , чем подход с использованием наборов, но все же ...
Перебрать array1 и найти его в array2. Если он найден, добавьте его в array3, если его еще нет.
for (MyObject* obj in array1)
{
if([array2 containsObject:obj] && ![array3 containsObject:obj])
[array3 addObject:obj];
}
Если в вашем array1 нет повторяющихся элементов, вам не нужна вторая проверка.
Похожие вопросы
Связанные вопросы
Новые вопросы
iphone
НЕ ИСПОЛЬЗУЙТЕ этот тег, если вы не обращаетесь конкретно к iPhone и / или iPod touch от Apple. Для вопросов, не зависящих от оборудования, используйте тег [ios]. Больше тегов, которые нужно рассмотреть, это [xcode] (но только если вопрос касается самой IDE), [swift], [target-c] или [cocoa-touch] (но не [cocoa]). Пожалуйста, воздержитесь от вопросов, касающихся iTunes App Store или iTunes Connect. Если вы используете C #, пометьте [mono].