2011-01-28 5 views
10

私は基本的な機能であると感じることを実行する必要がありますが、それを行う方法に関するドキュメントは見つかりません。助けてください!Objective-C:オブジェクトが配列内で発生する回数を数えますか?

配列内で特定のオブジェクトが何回発生したかをカウントする必要があります。例を参照してください:

array = NSArray arrayWithObjects:@"Apple", @"Banana", @"Cantaloupe", @"Apple", @"DragonFruit", @"Eggplant", @"Apple", @"Apple", @"Guava",nil]retain]; 

配列を繰り返し処理し、文字列@「Apple」が見つかった回数を数えますか?

ご協力いただきましてありがとうございます。

+1

これは一般的な操作である場合は、 'NSCountedSet'を使用しています。 – bbum

答えて

13

シンプルかつ具体的な答え:

int occurrences = 0; 
for(NSString *string in array){ 
    occurrences += ([string isEqualToString:@"Apple"]?1:0); //certain object is @"Apple" 
} 
NSLog(@"number of occurences %d", occurrences); 

PS:マーティンBabacaevの答えがあまりにもかなり良いです。反復はブロックでより速くなりますが、この特定のケースでは非常に少数の要素しかないので、明らかな利得はありません。私は(実施例)のブロックを使用して、そのかかわらず:)

+2

どうして 'occurrences + = [string isEqualToString:@" Apple "];'? –

+0

あなたは正しいです...もっと明確にしたかっただけです) – nacho4d

+0

申し訳ありませんが、この回答を受け入れるのは永遠に終わってしまいましたが、最高のもののように見えます!ありがとう! – EmphaticArmPump

3
- (int) numberOfOccurrencesForString:(NSString*)needle inArray:(NSArray*)haystack { 
    int count = 0; 

    for(NSString *str in haystack) { 
     if([str isEqualToString:needle]) { 
      count++; 
     } 
    } 

    return count; 
} 
16

もう一つの解決策を使用します。

NSInteger occurrences = [[array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {return [obj isEqual:@"Apple"];}] count]; 
NSLog(@"%d",occurrences); 
+0

こんにちはマーティン、この答えは、コンパイル時のエラーの原因となる無関係の終了括弧を持っています。私はSOで編集しようとしましたが、修正を提出するには最低6文字の編集が必要です。しかし、偉大なライン! – rob5408

+0

ありがとうRob!固定。 –

4

私は辞書(マップの客観Cのバージョン)にそれらを配置することをお勧めします。辞書のキーはオブジェクトであり、値はカウントでなければなりません。もちろん、MutableDictionaryでなければなりません。項目が見つからない場合は、追加してカウントを1に設定してください。

+1

@Robで述べたように、あなたの配列をループし、 'A'のような値をキーとして' NSMutableDictionary'を構築し、そのキーが値として見えるカウントを設定します。 – raidfive

2

私はRobの答えに投票しましたが、私はいくつかの助けになることを願っています。

NSArray *array = [[NSArray alloc] initWithObjects:@"A", @"B", @"B", @"B", @"C", @"D", @"E", @"M", @"X", @"X", nil]; 

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init]; 
for(int i=0; i < [array count]; i++) { 
    NSString *s = [array objectAtIndex:i]; 
    if (![dictionary objectForKey:s]) { 
     [dictionary setObject:[NSNumber numberWithInt:1] forKey:s]; 
    } else { 
     [dictionary setObject:[NSNumber numberWithInt:[dictionary objectForKey:s] intValue]+1 forKey:s]; 
    } 
} 

for(NSString *k in [dictionary keyEnumerator]) { 
    NSNumber *number = [dictionary objectForKey:k]; 
    NSLog(@"Value of %@:%d", k, [number intValue]); 
} 
2

問題の文のように配列がソートされている場合は、辞書を使用する必要はありません。

2つの連続する要素が同じであることがわかると、1つの直線掃引を実行してカウンタをインクリメントするだけで、ユニークな要素の数をより効率的に見つけることができます。

辞書解はO(nlog(n))であり、線形解はO(n)です。

はここで、線形解決のためのいくつかの擬似コードです:

array = A,B,B,B,B,C,C,D,E,M,X,X #original array 
array = array + -1 # array with a dummy sentinel value to avoid testing corner cases. 

# Start with the first element. You want to add some error checking here if array is empty. 
last = array[0] 
count = 1 # you have seen 1 element 'last' so far in the array. 
for e in array[1..]: # go through all the elements starting from the 2nd one onwards 
    if e != last: # if you see a new element then reset the count 
    print "There are " + count + " " + last elements 
    count = 1 # unique element count 
    else: 
    count += 1 
    last = e 
15

NSCountedSetを使用します。それは辞書より速く、その問題を正確に解決するように設計されています。

NSCountedSet *cs = [NSCountedSet new]; 
for(id anObj in someArray) 
    [cs addObject: anObj]; 

// then, you can access counts like this: 
.... count = [cs countForObject: anObj]; ... 

[cs release]; 
15

@bbumは、NSCountedセットを使用しています。

NSArray *array = [[NSArray alloc] initWithObjects:@"A", @"B", @"X", @"B", @"C", @"D", @"B", @"E", @"M", @"X", nil]; 
    NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array]; 
    NSLog(@"%@", countedSet); 

のNSLog出力: (D [1]、M [1]、E [1]、A [1]、B [3初期化thetカウントセットに直接配列に変換されますがあります]、X [2]、C [1])

だけでアクセス項目:

count = [countedSet countForObject: anObj]; ... 
+0

この回答は非常に良いです。しかし、NSCountedSetから重複メンバーを持つ配列を取得できますか? (例えば、それをplistファイルに格納するため)。 –

+0

これで、NSCountedSetを変換する方法が考えられました。<-> NSDictionary(キーはカウントされたセット内のオブジェクトで、値はカウントです)は、plistが小さくなるため、より良いでしょう。 私はグーグルで、何かを見つけることができませんでした。おそらく、このようなメソッドを手動で実装する必要があります。 –

0

あなたはそれがより一般的な場合、またはあなたは、アレイ内のequals /異なるオブジェクトをカウントしたい場合は、これを試してみてください。

記号 "!「DIFFERENT値をカウントします。あなたはSAME値をしたい場合は、削除し、 『!』

int count = 0; 
    NSString *wordToCheck = [NSString string]; 
    for (NSString *str in myArray) { 
    if(![str isEqualToString:wordToCheck]) { 
     wordToCheck = str; 
     count++; 
    } 
    } 

希望は、このコミュニティを助け!私はそれがのUITableViewのセクションの正しい数を追加するために使用しました

2

@bbumするための基準と@Zaph

NSArray *myArray = [[NSArray alloc] initWithObjects:@"A", @"B", @"X", @"B", @"C", @"D", @"B", @"E", @"M", @"X", nil]; 
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:myArray]; 

for (NSString *item in countedSet) { 

    int count = [countedSet countForObject: item]; 
    NSLog(@"the String ' %@ ' appears %d times in the array",item,count); 
} 

と完全なコードありがとうございました。あなたがこの方法を行うことができます

0

NSArray *array = [[NSArray alloc] initWithObjects:@"A", @"B", @"X", @"B", @"C", @"D", @"B", @"E", @"M", @"X", nil]; 

NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:array]; 
NSArray *uniqueStates = [[orderedSet set] allObjects]; 

NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array]; 
for(int i=0;i<[uniqueStates count];i++){ 
NSLog(@"%@ %d",[uniqueStates objectAtIndex:i], [countedSet countForObject: [uniqueStates objectAtIndex:i]]); 
} 

結果は次のようである:1

7

はちょうどこのかなり古い質問に出くわしました。私はNSCountedSetを使用してお勧めします:

NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array]; 
NSLog(@"Occurrences of Apple: %u", [countedSet countForObject:@"Apple"]); 
関連する問題