сравнить два массива и получить общие элементы - PullRequest
19 голосов
/ 30 августа 2011

У меня есть два массива, но они имеют разную длину .Я хочу сравнить эти два массива и поместить общие элементы в новый массив .Между тем там не должно быть дубликатов элементов это третий массив.Я действительно испортил это, пожалуйста, помогите мне.очень благодарен.,,

Ответы [ 3 ]

56 голосов
/ 30 августа 2011

Как-то так?

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];
4 голосов
/ 30 августа 2011

Третий подход (помимо использования наборов или простого цикла, проверяющего каждый элемент с содержимым) заключается в сортировке обоих массивах и последующем использовании двух индексов:

// 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 раза быстрее , чем подход с использованием множеств, но все же ...

2 голосов
/ 30 августа 2011

Перебрать массив1 и найти его в массиве2.Если он найден, добавьте его в array3, если у него его еще нет.

for (MyObject* obj in array1)
{ 
     if([array2 containsObject:obj] && ![array3 containsObject:obj])
        [array3 addObject:obj];
}

Если у вашего array1 нет повторяющихся элементов, вам не нужна вторая проверка.

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