Что такое хороший способ проверить наличие коллизий между объектами в массиве?
Я делал цикл 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];