0

I need to get the highest repeated character in string and the count of the repeated character. For that i stored the each character of the string in the array and using the for loops i got each character and the count. is there any other delegate methods to find it to reduce the code?

for example

NSRange theRange = {0, 1}; //{location, length}
NSMutableArray * array = [NSMutableArray array];
for ( NSInteger i = 0; i < [myFormattedString length]; i++) {
    theRange.location = i;
    [array addObject:[myFormattedString substringWithRange:theRange]];
}
int countForChar = 0;
for (int i=0; i<[array count]; i++) {
    NSString *firstCharacter = [array objectAtIndex:i];
    for (int j=1; j< [array count]; j++) {
        if ([firstCharacter isEqualToString:[array objectAtIndex:j]]) {
            countForChar = countForChar + 1;
        }
    }
    NSLog(@"The Charcter is %@ The count is %d", firstCharacter, countForChar);
    countForChar = 0;
}

Thanks in advance...

Bala
  • 136
  • 1
  • 1
  • 14
  • There is no standard api to do it you have to implement your own solution, but there is a faster way to do it, by using dictionary. – Basheer_CAD Feb 26 '14 at 10:13
  • @Basheer can you explain it – Bala Feb 26 '14 at 10:14
  • 1
    Is this for an interview? Also, this code will fail for decomposed characters and codepoints outside the BMP. As a hint, I suggest looking at NSCountedSet. – Jason Coco Feb 26 '14 at 10:18
  • @JasonCoco thanks i will look at NSCountedSet..not for an interview just need to reduce my code... – Bala Feb 26 '14 at 10:26
  • this link may help you to get count in easier way http://stackoverflow.com/questions/10584230/character-occurences-in-a-string-objective-c – Leena Feb 26 '14 at 12:13

4 Answers4

1

Here is my code might be not good enough but I think its the fastest

NSString *myFormattedString = @"oksdflajdsfd";

    NSMutableDictionary *lettersCount = [[NSMutableDictionary alloc] init];
    for (NSInteger i = 0; i < [myFormattedString length]; i++) {
        unichar charAtIndex = [myFormattedString characterAtIndex:i];
        NSNumber *countForThisChar = [lettersCount objectForKey:[NSString stringWithFormat:@"%c",charAtIndex]];
        int count = 1;
        if(countForThisChar) {
            count = [countForThisChar integerValue] + 1;
            [lettersCount setObject:@(count) forKey:[NSString stringWithFormat:@"%c",charAtIndex]];
        } else {
            // not added yet, add it with 1 count
            [lettersCount setObject:@(count) forKey:[NSString stringWithFormat:@"%c",charAtIndex]];
        }
    }

    // for now the work is O(n)

    // ignoring the work of this cycle or consider it as O(1)
    NSString *mostFrequentChar = nil;
    NSInteger maxCount = 0;
    for(NSString *oneChar in lettersCount.keyEnumerator) {
        NSNumber *count = [lettersCount objectForKey:oneChar];
        if([count integerValue] > maxCount) {
            mostFrequentChar = oneChar;
            maxCount = [count integerValue];
        }
    }

    NSLog(@"the char %@ met for %d times", mostFrequentChar, maxCount);

Remember the search for an object in NsDictionary is O(1) for the average case scenario.

Basheer_CAD
  • 4,908
  • 24
  • 36
1

Here is an example that would work correctly with any string and has linear time complexity. This uses the NSCountedSet which can be pretty useful.

NSString* string = @"This is a very wonderful string. Ølsen & ジェイソン";
NSCountedSet* characterCounts = [[NSCountedSet alloc] init];
// This ensures that we deal with all unicode code points correctly
[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
  [characterCounts addObject:substring];
}];
NSString* highestCountCharacterSequence = nil;
NSUInteger highestCharacterCount = 0;
for (NSString* characterSequence in characterCounts) {
  NSUInteger currentCount = [characterCounts countForObject:characterSequence];
  if (currentCount > highestCharacterCount) {
    highestCountCharacterSequence = characterSequence;
    highestCharacterCount = currentCount;
  }
}
NSLog(@"Highest Character Count is %@ with count of %lu", highestCountCharacterSequence, (unsigned long)highestCharacterCount);

Sadly, my silly example string ends up having space characters as the most repeated :)

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
  • I though of the same, but using a `NSDictionary` instead of an `NSCountedSet`. I'd suggest that in the `enumerateSubstringsInRange`, you'd add a escape "character unwanted, as space". Plus, do you get if there the same amount of occurrences of two characters? – Larme Feb 26 '14 at 10:49
  • @Larme If there were as set of unwanted characters, I'd probably create a character set of them and compare to that and just not add to the bag if I see one of those. However, Bala never mentioned if there were unwanted characters though, so this satisfies the requirement as written. If the max count < 2, you can assume no repeats. This will get a random character if there are more than one highest character count, but you could make a separate bag for that if you needed to return all or something. – Jason Coco Feb 26 '14 at 10:54
  • 1
    I know that these aren't asked by the user, but mentioning the "limits" could help other users who only look at the answer without thinking (and unfortunately there are quite a lot). – Larme Feb 26 '14 at 10:57
1

Because the string may have more than a char have same most repeat count, so here is my solution:

- (NSArray *)mostCharInString:(NSString *)string count:(int *)count{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    int len = string.length;
    NSRange theRange = {0, 1};
    for (NSInteger i = 0; i < len; i++) {
        theRange.location = i;
        NSString *charStr = [string substringWithRange:theRange];
        int preCount = 0;
        if ([dict objectForKey:charStr]) {
            preCount = [[dict objectForKey:charStr] unsignedIntegerValue];
        }
        [dict setObject:@(preCount+1) forKey:charStr];
    }
    NSArray *sortValues = [[dict allValues] sortedArrayUsingSelector:@selector(compare:)];
    *count = [[sortValues lastObject] unsignedIntegerValue];
    return  [dict allKeysForObject:@(*count)];
}

How to use and test:

int mostRepeatCount = 0;
NSArray *mostChars = nil;
mostChars = [self mostCharInString:@"aaabbbcccc" count:&mostRepeatCount];
NSLog(@"count:%d char:%@", mostRepeatCount, mostChars);

the result is:

count:4 char:(
    c
)

try:

mostChars = [self mostCharInString:@"aaabbbccccdddd" count:&mostRepeatCount];

the result is:

count:4 char:(
    d,
    c
)

Hope to help you.

simalone
  • 2,768
  • 1
  • 15
  • 20
0

Every character can be presented by its int value. Make an instance of NSArray with n size (n number of unique characters string can have). Loop through string and add +1 on (int)character index in array at every cycle. When you finish the character with greatest value in array is the highest repeated character.

damirstuhec
  • 6,069
  • 1
  • 22
  • 39