2012-02-28 2 views
5

У меня есть пользовательский класс, называемый card, и мне нужно создать набор из 10 уникальных карт из массива карт случайного размера. Кроме того, мне нужно включить любые белые списки, чтобы убедиться, что они всегда включены.NSMutableSet содержит дубликаты

Моя проблема - карточки из белого списка (и только белый список), которые потенциально дублируются в наборе. Карты, случайно добавленные, никогда не дублируются, и подсчет всегда правильный (10). Я не могу понять, почему isEqual, похоже, работает иногда, но не всегда.

Вот где я создаю множество (randoms является массивом потенциальных карт ковыряться с):

NSMutableSet *randomCards = [NSMutableSet setWithCapacity:10]; 

[randomCards addObjectsFromArray:whiteListArray]; 

while ([randomCards count] < 10) { 
    NSNumber *randomNumber = [NSNumber numberWithInt:(arc4random() % [randoms count])]; 
    [randomCards addObject:[randoms objectAtIndex:[randomNumber intValue]]]; 
} 

Я отменяю метод isEqual для моего card класса на основе другой вопрос ответил здесь:

- (BOOL)isEqual:(id)other { 

if (other == self) 
    return YES; 
if (!other || ![other isKindOfClass:[self class]]) 
    return NO; 
return [self isEqualToCard:other]; 

} 

- (BOOL)isEqualToCard:(Card *)myCard { 

if (self == myCard) { 
    return YES; 
} 
if ([self cardName] != [myCard cardName] && ![(id)[self cardName] isEqual:[myCard cardName]]) 
    return NO; 

return YES; 
} 

Кажется, что он отлично работает, за исключением случаев, когда я добавляю в белые списки, я не могу понять, как я заканчиваю дубликаты (но не более 2 копий).

ответ

15

Вам необходимо переопределить hash в дополнение к isEqual.

На самом деле вы всегда необходимо убедиться, что эти два метода работают вместе. От Apple's documentation:

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

Что-то, как это должно работать:

- (NSUInteger)hash { 
    return [[self cardName] hash]; 
} 

Таким образом, ваш хэш зависит от той же информации, что вы используете, чтобы сделать сравнение.

Хэш используется структурами данных, такими как NSMutableSet, чтобы быстро группировать объекты в разные ковши. Важно, чтобы, если два объекта равны, они имеют одно и то же значение хэш-функции. (Все нормально, если два объекта имеют одинаковый хэш, но не равны, поэтому вы всегда можете вернуть тот же номер из hash, но тогда ваша производительность будет такой же, как с использованием массива. Структуры данных!)

+0

Ah отлично, спасибо. Я вел себя по неправильному пути, потому что это работало иногда, а не другие. – hokiewalrus

Смежные вопросы