2012-02-28 5 views
5

私はcardというカスタムクラスを持っています。ランダムなサイズのカードの配列から10個のユニークなカードのセットを作成する必要があります。また、常にホワイトリストに記載されたカードを含めて、それらが常に含まれていることを確認する必要があります。NSMutableSetには重複が含まれています

私の問題は、ホワイトリストのカード(そしてホワイトリストのみ)がセットに潜在的に複製されていることです。ランダムに追加されたカードは決して複製されず、カウントは常に正しい(10)。 isEqualが時々動作するように見える理由はわかりませんが、必ずしもそうではありません。

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]]]; 
} 

は、私は別の質問への答えに基づいて、私の cardクラスの isEqualメソッドをオーバーライド:

私は( randomsから選ばれる可能性のカードの配列である)セットを作成するのはここ

です

- (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; 
} 

ホワイトリストカードに追加する場合を除いて、完全に動作するように見えますが、私はどのように複製されてしまっているのか分かりません。

答えて

15

isEqualに加えて、hashを上書きする必要があります。

実際、常には、これら2つの方法が一緒に機能することを確認する必要があります。 Apple's documentationから

2つのオブジェクトが等しい場合(isEqual:メソッドで決定)、それらのハッシュ値は同じである必要があります。この最後の点は、サブクラスでハッシュを定義し、そのサブクラスのインスタンスをコレクションに入れる場合に特に重要です。このような

何か作業をする必要があります:

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

あなたのハッシュは、あなたが比較を行うために使用している同じ情報に依存してこの方法です。

ハッシュは、NSMutableSetのようなデータ構造によって使用され、オブジェクトを異なるバケットに素早くグループ化します。 2つのオブジェクトが等しい場合、同じハッシュ値を持つことが重要です。しかし、2つのオブジェクトが同じハッシュを持っていても等しくない場合は、hashから常に同じ番号を返すことができますが、配列を使用する場合と同じパフォーマンスになります。

+0

Ah完璧、ありがとう。私は間違った道のりで自分自身を導いていました。なぜなら、ときどき働くように思えたからです。 – hokiewalrus

関連する問題