6

と呼ばれるカスタムクラスがcardあり、ランダムなサイズのカードの配列から10枚の一意のカードのセットを作成する必要があります。また、ホワイトリストに登録されているカードを最初に含めて、常に含まれるようにする必要があります。

私の問題は、ホワイトリストのカード(およびホワイトリストのみ)がセット内で重複している可能性があることです。ランダムに追加されたカードが複製されることはなく、カウントは常に正しいです(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部を超えることはありません)。

4

1 に答える 1

17

hashに加えてオーバーライドする必要がありますisEqual

実際、これら2つの方法が一緒に機能することを常に確認する必要があります。Appleのドキュメントから:

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

このようなものが機能するはずです:

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

このように、ハッシュは、比較に使用しているのと同じ情報に依存します。

ハッシュは、NSMutableSetオブジェクトをさまざまなバケットにすばやくグループ化するなどのデータ構造によって使用されます。2つのオブジェクトが等しい場合、それらが同じハッシュ値を持つことが重要です。(ただし、2つのオブジェクトのハッシュが同じであるが等しくない場合は問題ありません。したがって、から常に同じ数値を返すことができますがhash、パフォーマンスは配列を使用した場合と同じになります。データ構造!)

于 2012-02-28T19:26:44.483 に答える