2011-11-08 9 views
6


NSNumbersをロードしたシンプルなNSSetを持っていて、それらの数値がすでにセットに追加されているかどうかを調べたいと思います。私はこれを行うと:NSNumbersのNSSet - メンバーメソッドは常にゼロです

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    // something... 
} 

問題は、これらの数字が同じであっても、(falseの場合)メンバーは常にnilを返すということです。 isEqualメソッドはtrueを返します。だから私はメンバーメソッドがのisEqualを使用していることを読んで、ドキュメントで

if([num1 isEqual:num2]){ 
    // correct 
} 

作品...
はので、私は...、問題が何であるかを任意のアドバイスを 感謝を知りません。

+0

あなたのコードが正しくペーストされている - あなたのセットにnum2のオブジェクトを追加していない – Maggie

+0

あなたのコードは私にとって完璧にうまくいっていますか? – Devarshi

+0

@Maggieはい私は確信していますが、ポイントは、5番目のセットがすでにセットに入っているかどうかを確認したいのですが、nsnumberはオブジェクトなので使用しなければならないので、値が5のnsnumberオブジェクトがすでにセットに入っています(値5のnum1は真です) – haluzak

答えて

2

num1num2が同じオブジェクトであるかどうかを確認することが問題です。そして彼らはそうではありません。彼らはちょうど同じ値を持っていますが、同じ値を持つ2つの異なるオブジェクトです。

だから、memberでチェックしているのは、同じアドレスがメモリにあるかどうかです。

編集:番号の値が同じかどうか確認するには、compareを使用する必要があります。

+0

"彼らは同じ住所を持っているかどうかメモリ内 "は真実ではありません。 'member:' docs: "セットにオブジェクト(isEqual :)で指定されたオブジェクトと等しいオブジェクトが含まれていればそのオブジェクト(通常はオブジェクト)になり、そうでなければnilになります。 – Wevah

+0

あなたはどちらも正しいかもしれません...私は、NSNumberが最初のいくつかの整数の静的表現を持つ卑劣な最適化を持っていることを思い出しているようです。この場合、メモリアドレス_and_ isEqualは動作します。 – jrturton

+0

確かに、どちらの方法でもfalseを返してはいけません。 – Wevah

4

オブジェクトではなくNSNumbersの値を比較する必要があります。

あなたはobjectsPassingTest:

例を使用することができます。

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
NSNumber *num3 = [NSNumber numberWithInt:3]; 
[set addObject:num1]; 

NSSet *filteredSet; 
filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num2]; 
}]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num3]; 
}]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

のNSLog出力:

Contains num2: YES 
Contains num3: NO 

場合や述語を使用して、所望される:

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num2]]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num3]]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 
2

タラこんにちはワードがログに書き込まれているので、あなたがたNSArrayを使用する場合、私はそれを

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    NSLog(@"Hello, world"); 
    } 
+0

これはかなり有効ではありません。なぜなら、それをセットに追加した後に* num1の値を6に変更し、[set member num1]と[set member num2]の両方がtrueを返すことを尋ねるからです。 –

+0

@RyanHeitner、どのようにNSNumberオブジェクトを変更できますか?彼らは不変です! – ragnarius

+0

NSNumber * num1 = [NSNumber numberWithInt:5]; [set addObject:num1]; num1 = [NSNumber numberWithInt:6]; –

4

を実行するかわりに、オブジェクト自体の値を比較する必要があるときにeが動作します。 NSArrayを使用する代わりに、NSMutableIndexSetを使用できます。これにより、いくつかのステップを少なくして値を比較することができます。

//during init, add some numbers 
NSMutableIndexSet *tSet = [[NSMutableIndexSet alloc] init]; 
NSUInteger exampleValue = 7; 
[tSet addIndex:exampleValue]; 
exampleValue = 42; 
[tSet addIndex:exampleValue]; 

//...later on 
//look to see if numbers are there 
if ([tSet containsIndex:7]){ 
    NSLog(@"7 exists!"); 
} 
if ([tSet containsIndex:8]){ 
    NSLog(@"8 exists!"); 
} 

出力: 7が存在します!

関連する問題