NSSet -member для проверки равенства NSValue

У меня есть NSSet содержащий много тысяч объектов NSValue (обертывание CGPoints ). Я бы очень быстро нашел, существует ли заданное значение CGPoint в NSSet . Мне кажется, что метод member: метод NSSet может выполнять эту работу здесь, за исключением того, что он проверяет равенство, используя isEqual: Объекты NSValue используют isEqualToValue: и поэтому, когда я выполняю код:

 [mySet member:valueToCheck]; 

это фактически приводит к сбою Xcode.

1) Есть ли способ использовать пользовательскую проверку равенства, чтобы сделать эту работу объектами NSValue ?

2) Это даже лучший подход (т. Е. member: достаточно быстрый, в первую очередь)? Сценарий заключается в том, что у меня есть NSSet содержащий большое количество точек, представляющих пиксели на экране (iPad). Позже мне нужно бомбардировать этот набор со многими тысячами точек в секунду, чтобы увидеть, существуют ли они в наборе. Мой подход кажется грубым для достижения этого. Я думал о создании чего-то вроде огромного двумерного битового массива, причем каждый индекс представлял пиксель на экране. Как только я знаю, на что я тестирую, я могу просто перейти прямо к этой точке массива и проверить 1 или 0 … это звучит лучше или хуже?

благодаря

Можете ли вы получить это в простом воспроизводимом случае? Например, я просто попробовал:

 NSValue *v = [NSValue valueWithCGPoint:CGPointMake(1, 1)]; NSSet *s = [NSSet setWithObject:v]; NSLog(@"%@", [s member:[NSValue valueWithCGPoint:CGPointMake(1, 1)]]); 

Но все работает отлично.

редактировать

-isEqual: это не проблема:

 NSValue *v1 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSValue *v2 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSLog(@"%d", [v1 isEqual:v2]); //logs "1" 

-hash не проблема:

 NSLog(@"%d", ([v1 hash] == [v2 hash])); //logs "1" 

Это разные объекты:

 NSLog(@"%d", (v1 != v2)); //logs "1" 

Проблема в вашем коде. Попробуйте очистить и перестроить.

Отвечать нет. 2:

Я не знаю, как NSSet реализуется внутренне, но учитывая, что вы знаете, что вы храните точки (с X и Y), я думаю, вам будет лучше, реализовав свой собственный алгоритм секционирования. Лично я бы выбрал свою собственную реализацию над NSSet, если вы скажете, что у вас тысячи баллов.

Хранение огромных двумерных массивов для каждого пикселя, вероятно, будет самым быстрым способом, но это убьет вас с точки зрения потребления памяти. Вам нужно что-то быстрое, но и легкое.

Есть много алгоритмов, и вы можете найти их, выполнив поиск «алгоритмов пространственного разбиения» на wikipedia или google. Это также зависит от ваших навыков программирования и того, сколько времени вы готовы инвестировать в это.

Например, довольно простым было бы реализовать четырехъядерное дерево, в котором вы начинаете погружать свой экран (или область) в 4 равные части. Затем, если и где необходимо, вы делите эту конкретную ячейку также на 4 части. И вы делаете это до тех пор, пока каждая ячейка не будет содержать достаточно небольшое количество точек, чтобы вы могли проверять все эти ошибки. Вы можете найти очень хорошее описание на wiki: http://en.wikipedia.org/wiki/Quadtree

Надеюсь это поможет,

[mySet member:valueToCheck] не должен сбой. NSValue isEqual: отлично работает, когда я пытаюсь его здесь, и на самом деле, вероятно, вызывает isEqualToValue: когда ему дается другое сравнение NSValue. Действительно ли valueToCheck NSValue, или это CGPoint?

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

 CFSetCallBacks callbacks = kCFTypeSetCallBacks; callbacks.equal = customEqualFunction; callbacks.hash = customHashFunction; NSMutableSet *set = (NSMutableSet *)CFSetCreateMutable(NULL, 0, &callbacks); 

Ограничения на эти функции, по-видимому, такие же, как в hash isEqual: и isEqual: методы, все, что равно, должно иметь одинаковый хеш. Прототипы C-стиля для customEqualFunction и customHashFunction описаны здесь и здесь .

Одним из решений было бы подклассы NSSet и переопределить member: сделать свое собственное сравнение. Тогда ваше собственное сравнение может быть простым вызовом isEqualToValue: Посмотрите примечания к подклассам в документации NSSet .

Другим подходом было бы добавление категории в NSValue которая реализует isEqual: В этом случае я бы предпочел подклассу, потому что это более ограниченное решение.

Это проблема не только с -isEqual: вас также может быть проблема с методом -hash . Если вы хотите использовать NSSet, вы, вероятно, должны создать собственный класс, который обертывает CGPoint. -isEqual: тогда тривиально, и -hash может быть реализован каким-то методом объединения бит обеих координат, а затем рассматривается как NSUInteger.

Вы также захотите реализовать протокол NSCopying , который также является тривиальным, если ваши точки неизменяемы (просто сохраните и верните self в -copyWithZone: .

Interesting Posts
Давайте будем гением компьютера.