Что такое хороший способ проверить наличие коллизий между объектами в массиве?

Я делал цикл for внутри другого цикла for, чтобы получить 2 объекта из массива одновременно, но должен быть лучший способ. Я просто хочу проверить, не сталкиваются ли они, а затем удалить их из вида и массива.

4 ответа

Вы использовали слово collide в вашем вопросе, не сказав нам, что вы имели в виду - поэтому другие ответы пока не помогают:) Они говорят о столкновении, как в "дубликатах элементов в словаре / массиве", но вы имеете в виду столкновение, как в overlay on the screen,

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

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

Если вы еще этого не сделали, вы можете попробовать это оптимизировать внутренний цикл:

// Compare each image with the others to see if they overlap
NSMutableSet *colliding = [NSMutableSet new];
for (NSInteger indexA = 0; indexA < myImages.count; ++indexA) {
    UIView *a = [myImages objectAtIndex:indexA];
    CGRect rectA = a.frame;

    for (NSInteger indexB = indexA; indexB < myImages.count; ++indexB) {
        UIView *b = [myImages objectAtIndex:indexB];
        if (a==b) continue;

        CGRect rectB = b.frame;
        CGRect intersection = CGRectIntersect(rectA, rectB);
        if (NO == CGRectIsNull(intersection)) {
            [colliding addObject:a];
            [colliding addObject:b];
        }
    }
}

// Remove the colliding images
for (UIView *c in colliding) {
    [c removeFromSuperview];
    [myImages removeObject:c];
}

Вы можете использовать NSCountingSet.

NSArray *array = [[NSArray alloc] initWithObjects:@"1",@"1",@"0",nil];
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:array];
NSLog(@"%@",set); // (1 [2], 0 [1]) // object 1 is collide 
for(id obj in set)
{
    if ([set countForObject:obj]>1) {
        //collide
    }
}

NSArrayс containsObject: метод, который вы можете использовать вместо внутреннего цикла. Но это может быть быстрее (кто-то должен сравнить и увидеть), чтобы поместить все объекты из одного в набор ([NSSet setWithArray:]) и перебрать другой массив, проверяя, есть ли они в наборе. Или конвертируйте их обоих и используйте intersectSet: (на изменяемой копии). Я предполагаю, что метод set будет быстрее, так как массивы будут увеличиваться, но это не будет иметь значения для ваших чисел.

Вы ищете способ найти объекты, которые находятся в двух разных массивах одновременно?

Если это так, я рекомендую использовать indexesOfObjectsPassingTest: из NSArray,

@implementation NSArray (Comparison)
- (NSIndexSet *)indexesOfObjects:(NSArray *)objects {
    return [self indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
        return [objects containsObject:obj];
    }];
}
- (NSArray *)objectsCommonWithArray:(NSArray *)array {
    return [self objectsAtIndexes:[self indexesOfObjects:array]];
}
@end

Тогда вы можете сделать это:

// assuming array1 and array2 exist.
NSArray *commonObjects = [array2 objectsCommonWithArray:array2];
Другие вопросы по тегам