ios NSPredicate to find nearest value in NSDictionary - ios

I have an array of dictionaries like this:
(
{ key = 1, value = 40},
{ key = 4, value = 50},
{ key = 8, value = 60}
}
These are like this,
for >=1 item cost is 40,
for >=4 item cost is 50 and like wise.
I would like to get the value for 5, which in this case is 50.
The piece of code I have tried is:
NSMutableArray *wallpaperPriceArray = [[NSMutableArray alloc]init]; // Assuming this has all the dictionary values
float wallpaperPriceValue = 0;
int itemNumber = 0;
for (int i = 0; i<wallpaperPriceArray.count; i++) {
int check = 0;
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i] objectForKey:#"value"] floatValue];
check++;
}
if(i + 1 <= wallpaperPriceArray.count)
{
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i+1] intValue] && itemNumber < [[wallpaperPriceArray objectAtIndex:i+1] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i+1] objectForKey:#"value"] floatValue];
check++;
if(check == 2)
{
break ;
}
}
}
if(i + 2 <= wallpaperPriceArray.count)
{
if(itemNumber >= [[wallpaperPriceArray objectAtIndex:i+2] intValue] && itemNumber < [[wallpaperPriceArray objectAtIndex:i+2] intValue])
{
wallpaperPriceValue = [[[wallpaperPriceArray objectAtIndex:i+2] objectForKey:#"value"] floatValue];
check++;
if(check == 2)
{
break ;
}
}
}

I Don't think the predicate is the right thing, Better would be to enumerate the objects here is some sample code:
NSArray *array = #[
#{ #"key" : #(1), #"value" : #(40)},
#{ #"key" : #(4), #"value" : #(50)},
#{ #"key" : #(8), #"value" : #(60)}
];
NSInteger searchedValue = 5; // <---
__block NSDictionary *closestDict = nil;
__block NSInteger closestValue = 0;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *dict = obj;
NSInteger key = [dict[#"key"] integerValue];
// Check if we got better result
if(closestDict == nil || (key > closestValue && key <= searchedValue)){
closestDict = dict;
closestValue = key;
if(key == searchedValue) { *stop = YES; }
}
}];
NSLog(#"value %#", closestDict);

I would suggest in addition to above answer to use the spline method to get the value needed, this is in the link
https://github.com/soffes/SAMCubicSpline
Using this library would solve the question as follows:
NSArray *array = #[
#{ #"key" : #(1), #"value" : #(40)},
#{ #"key" : #(4), #"value" : #(50)},
#{ #"key" : #(8), #"value" : #(60)}];
SAMCubicSpline *spline = [[SAMCubicSpline alloc] initWithPoints:#[
[NSValue valueWithCGPoint:CGPointMake(1.0f, 40.0f)],
[NSValue valueWithCGPoint:CGPointMake(4.0f, 50f)],
[NSValue valueWithCGPoint:CGPointMake(8.0f, 60.0f)],
]];
then you can obtain any value by this
CGFloat y = [spline interpolate:x];

Related

Max value for each object in an Array of Dictionaries

I have an array of dictionaries that I am trying to get the Max score for each player in the array. Each player can have multiple entries I am trying to get an array of dictionaries of each players best score.
NSArray
[0] - NSDictionary
- [0] Score: (double)20.7
- [1] NameID: (int) 1
- [2] Date
[1] - NSDictionary
- [0] Score: (double)25
- [1] NameID: (int) 1
- [2] Date
[2] - NSDictionary
- [0] Score: (double)28
- [1] NameID: (int) 2
- [2] Date
[3] - NSDictionary`
- [0] Score: (double)26
- [1] NameID: (int) 3
- [2] Date
I have tried using NSPredicate predicateWithFormat but I am only able to get back the max for everything in the array not related to the name.
Expected Output:
NSArray
[1] - NSDictionary
- [0] Score: (double)25
- [1] NameID: (int) 1
- [2] Date
[2] - NSDictionary
- [0] Score: (double)28
- [1] NameID: (int) 2
- [2] Date
[3] - NSDictionary`
- [0] Score: (double)26
- [1] NameID: (int) 3
- [2] Date
Thanks for the help.
You can't use an NSPredicate for this, since you want to determine the maximum score for several different players. Under the covers, NSPredicate iterates the array anyway, so using your own loop isn't any less efficient. In the following code I have assumed that the scores and player names are wrapped in NSNumber
-(NSArray *)maxScoresForPlayers:(NSArray *)playerScores {
NSMutableDictionary *maxScores = [NSMutableDictionary new];
for (NSDictionary *player in playerScores) {
NSNumber *playerID = (NSNumber *)player[#"NameID"];
NSDictionary *playerMax = maxScores[playerID];
if (playerMax == nil) {
playerMax = player;
} else {
NSNumber *currentMax = (NSNumber *)[playerMax[#"Score"];
NSNumber *playerScore = (NSNumber *)player[#"Score"];
if ([playerScore doubleValue] > [currentMax doubleValue]) {
playerMax = player;
}
}
maxScores[playerID] = playerMax;
}
return([maxScores allValues];
}
You can do it manually like this:
NSMutableDictionary *maxScoresDict = [NSMutableDictionary dictionary];
for (NSDictionary *score in scoresArray) {
NSNumber *key = score[#"NameID"];
NSNumber *savedMax = maxScoresDict[key][#"Score"];
NSNumber *currentMax = maxScoresDict[key][#"Score"];
if (savedMax == nil || [currentMax doubleValue] > [savedMax doubleValue]) {
maxScoresDict[key] = score;
}
}
NSArray *maxScoresArray = [maxScoresDict allValues];
Try this:
NSArray *objects = #[#{#"Score": #(20.7),
#"NameID": #(1),
#"Date": [NSDate date]},
#{#"Score": #(25),
#"NameID": #(1),
#"Date": [NSDate date]},
#{#"Score": #(28),
#"NameID": #(2),
#"Date": [NSDate date]},
#{#"Score": #(26),
#"NameID": #(3),
#"Date": [NSDate date]}];
NSMutableArray *users = [NSMutableArray array];
for (NSInteger i=0; i<objects.count; i++) {
NSDictionary *dict = objects[i];
NSNumber *nameID = dict[#"NameID"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.NameID==%#", nameID];
NSInteger index = [users indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL found = [predicate evaluateWithObject:obj];
return found;
}];
if (index != NSNotFound) {
NSNumber *score1 = dict[#"Score"];
NSNumber *score2 = users[index][#"Score"];
if (score1.doubleValue > score2.doubleValue) {
[users replaceObjectAtIndex:index withObject:dict];
}
}
else {
[users addObject:dict];
}
}
NSLog(#"%#", users);
- (NSArray *)getBestScores:(NSArray *)players {
NSMutableDictionary *best = [[NSMutableDictionary alloc] init];
for (NSDictionary *p in players) {
NSDictionary *b = [best valueForKey:[p valueForKey:#"NameID"]];
if (!b || [[p valueForKey:#"Score"] doubleValue] > [[b valueForKey:#"Score"] doubleValue])
[best setValue:p forKey:[p valueForKey:#"NameID"]];
}
return [best allValues];
}
// Get Max Value of integer element from Array of Dictonaries.
// Example Array Starts
<paramArray>(
{
DicID = 1;
Name = "ABC";
ValuetoCalculateMax = 2800;
},
{
DicID = 2;
Name = "DEF";
ValuetoCalculateMax = 2801;
},
{
DicID = 3;
Name = "GHI";
ValuetoCalculateMax = 2805;
}
)
// Example Array Ends
// Implementation
int MaxintegerValue=0;
MaxintegerValue=[self getMaxValueFromArrayofDictonaries:paramArray];
// Implementation Ends
// Function Starts
-(int)getMaxValueFromArrayofDictonaries:(NSArray *)paramArray
{
int MaxValue=0;
NSMutableDictionary *dic=[[NSMutableDictionary alloc]init];
for ( int i=0; i<[paramArray count]; i++ )
{
dic=[paramArray objectAtIndex:i];
if ([[dic valueForKey:#"ValuetoCalculateMax"] intValue] > MaxValue)
{
MaxValue=[[dic valueForKey:#"ValuetoCalculateMax"] intValue];
}
else
{
MaxValue=MaxValue;
}
}
return MaxValue;
}
// Function Ends
What you need to do is find scores for each user, then find the max score out of it.
- (void)findMaxScoreForUser:(int)userId {
NSDictionary *dict0 = [NSDictionary dictionaryWithObjects:#[#27.0,#3] forKeys:#[#"Score",#"UserID"]];
NSDictionary *dict1 = [NSDictionary dictionaryWithObjects:#[#25.0,#2] forKeys:#[#"Score",#"UserID"]];
NSDictionary *dict2 = [NSDictionary dictionaryWithObjects:#[#23.0,#3] forKeys:#[#"Score",#"UserID"]];
NSArray *arr = [NSArray arrayWithObjects:dict0,dict1,dict2, nil];
NSMutableArray *scores = [NSMutableArray array];
for (NSDictionary *dict in arr) {
int userID = [[dict valueForKey:#"UserID"] intValue];
if (userId == userID) {
[scores addObject:[dict valueForKey:#"Score"]];
}
}
int max = [[scores valueForKeyPath:#"#max.intValue"] intValue];
}

IOS: how to join 2 Dictionaries into 1 dictionary??

in my project i applied the following code
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSLog(#" for ref id =%# ,name of diagnose=%# data is= %#",refidstr,diagnosedictforname ,diagnosisdict);
and the output in console is comes out as in the form
str : {
diagnoses = (
{
Diagnoses = {
"diagnosis_name" = "TRANSIENT ISCHEMIA";
};
DiagnosesHospitals = {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
};
}
);
response = 200;
}
ref id =3341 ,name of diagnose={
"diagnosis_name" = "TRANSIENT ISCHEMIA";
} data is= {
"charge_amt" = "1300.00";
discharges = "11200.00";
"hospital_id" = 3341;
id = 163080;
"medicare_amt" = "100.00";
"total_amt" = "1100.00";
}
now i just want to embed the values of both the Dictionaries into one dictionary
someone please help me to sort out this issue.
Make a mutable copy of the first dictionary:
NSMutableDictionary * mutDic = [dic1 mutableCopy];
and then:
[mutDic addEntriesFromDictionary:dic2];
Try this code:
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
NSMutableDictionary *diagnosisdict = [[[dict6 objectForKey:#"diagnoses"] objectAtIndex:0] objectForKey:#"DiagnosesHospitals"];
NSDictionary *diagnosedictforname = [[[dict6 objectForKey:#"diagnoses"]objectAtIndex:0]objectForKey:#"Diagnoses"];
NSArray *keys = [diagnosedictforname allKeys];
for (int i =0; i < keys.count; i++) {
NSString *key = [keys objectAtIndex:i];
[diagnosisdict setValue:[diagnosedictforname valueForKey:key] forKey:key];
}
NSLog(#"your dic -> %#", diagnosisdict);

Sort NSArray to a particular sequence using an NSComparisonResult

I'm trying to sort my arrays with a particular sequence using an NSComparisonResult. I'm unable to figure out how to achieve the sequence I'm wanting.
I'm trying to weight Emojis towards the top (sequence of Emojis doesn't matter), followed by A-Z letters with giving a weight towards lowercase before uppercase, followed by numbers, followed by punctuation, then by symbols, and whatever else after that I dont care about at this point. I've gotten pretty close so far, but am still coming up short with what I want.
The sequence I'm trying to achieve would look like this as the output:
("\Ud83d\Ude03",
a,
A,
aa,
aA,
ab,
aB,
a1,
A1,
1,
01,
11,
001,
0001,
1001,
"#",
"#a",
"#1",
"$12",
"$0012")
Based upon this array as the input:
#[ #"a", #"aA", #"aa", #"A", #"aB", #"11", #"1001", #"ab", #"001", #"01",
#"a1", #"A1", #"😃", #"0001", #"1", #"#", #"$12", #"$0012", #"#a", #"#1" ];
But this is the output I'm getting:
("\Ud83d\Ude03",
a,
A,
aA,
aa,
aB,
ab,
a1,
A1,
0001,
001,
01,
1,
1001,
11,
"#a",
"#1",
"$0012",
"$12",
"#")
Code:
- (NSArray *)sortedArray:(NSArray *)input
{
NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSString *nameOne = obj1;
NSString *nameTwo = obj2;
NSString *startOne;
NSString *startTwo;
NSInteger currentIndex = 0;
NSInteger maxIndex = (nameOne.length < nameTwo.length) ? nameOne.length : nameTwo.length;
NSCharacterSet *decimalDigitCharSet = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *punctuationCharSet = [NSCharacterSet punctuationCharacterSet];
NSCharacterSet *symbolCharSet = [NSCharacterSet symbolCharacterSet];
NSMutableCharacterSet *nonPriorityCharSet = [[NSMutableCharacterSet alloc]init];
[nonPriorityCharSet formUnionWithCharacterSet:punctuationCharSet];
[nonPriorityCharSet formUnionWithCharacterSet:symbolCharSet];
do
{
if (currentIndex < maxIndex)
{
startOne = [nameOne substringWithRange:NSMakeRange(currentIndex, 1)];
startTwo = [nameTwo substringWithRange:NSMakeRange(currentIndex, 1)];
currentIndex++;
}
else
{
if (nameOne.length == nameTwo.length)
{
return NSOrderedSame;
}
else
{
return (nameOne.length < nameTwo.length) ? NSOrderedAscending : NSOrderedDescending;
}
}
}
while ([startOne isEqualToString:startTwo]);
{
NSRange rangeOne = [startOne rangeOfCharacterFromSet:nonPriorityCharSet];
NSRange rangeTwo = [startTwo rangeOfCharacterFromSet:nonPriorityCharSet];
if (rangeOne.length > 0 || rangeTwo.length > 0)
{
return (rangeOne.length > 0) ? NSOrderedDescending : NSOrderedAscending;
}
NSRange decimalRangeOne = [startOne rangeOfCharacterFromSet:decimalDigitCharSet];
NSRange decimalRangeTwo = [startTwo rangeOfCharacterFromSet:decimalDigitCharSet];
if (decimalRangeOne.length > 0 || decimalRangeTwo.length > 0)
{
if (decimalRangeOne.length == decimalRangeTwo.length)
{
return (startOne.intValue > startTwo.intValue) ? NSOrderedDescending : NSOrderedAscending;
}
else if (decimalRangeOne.length > decimalRangeTwo.length)
{
return NSOrderedDescending;
}
else if (decimalRangeTwo.length > decimalRangeOne.length)
{
return NSOrderedAscending;
}
}
}
return [nameOne localizedCaseInsensitiveCompare:nameTwo];
}];
return newArray;
}
You started well. But you didn't properly check for all the rules that you have set. I have created some categories based on you rules, and sort using them.
- (NSArray *)sortedArray:(NSArray *)input
{
__block id blocksafeSelf = self;
NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString *nameOne = obj1;
NSString *nameTwo = obj2;
NSInteger currentIndex = 0;
unichar charOne = [nameOne characterAtIndex:0];
unichar charTwo = [nameTwo characterAtIndex:0];
short maxLength = MIN(nameOne.length, nameTwo.length);
do {
charOne = [nameOne characterAtIndex:currentIndex];
charTwo = [nameTwo characterAtIndex:currentIndex];
currentIndex ++;
}
while (charOne == charTwo && currentIndex < maxLength);
short oneCategory = [blocksafeSelf getCharCategory:charOne];
short twoCategory = [blocksafeSelf getCharCategory:charTwo];
if (oneCategory != twoCategory) {
return oneCategory > twoCategory;
}
else if (oneCategory != 1) {
if (nameOne.length != nameTwo.length) {
return nameOne.length > nameTwo.length;
}
else {
return charOne > charTwo;
}
}
else {
if (nameOne.length != nameTwo.length) {
return nameOne.length > nameTwo.length;
}
else {
oneCategory = [blocksafeSelf getLetterCategory:charOne];
twoCategory = [blocksafeSelf getLetterCategory:charTwo];
if (oneCategory == twoCategory) {
return charOne > charTwo;
}
else {
unichar tempCharOne = oneCategory == 7 ? charOne + 32 : charOne;
unichar tempCharTwo = twoCategory == 7 ? charTwo + 32 : charTwo;
if (tempCharOne != tempCharTwo) {
return tempCharOne > tempCharTwo;
}
else {
return oneCategory > twoCategory;
}
}
}
}
return [nameOne localizedCaseInsensitiveCompare:nameTwo];
}];
return newArray;
}
- (short)getCharCategory:(unichar)character {
if (character > 255) { // emoji
return 0;
}
NSCharacterSet *letterCaseCharSet = [NSCharacterSet letterCharacterSet];
if ([letterCaseCharSet characterIsMember:character]) return 1;
NSCharacterSet *decimalDigitCharSet = [NSCharacterSet decimalDigitCharacterSet];
if ([decimalDigitCharSet characterIsMember:character]) return 2;
NSCharacterSet *punctuationCharSet = [NSCharacterSet punctuationCharacterSet];
if ([punctuationCharSet characterIsMember:character]) return 3;
NSCharacterSet *symbolCharSet = [NSCharacterSet symbolCharacterSet];
if ([symbolCharSet characterIsMember:character]) return 4;
return 5;
}
- (short)getLetterCategory:(unichar)character {
NSCharacterSet *lowerCaseCharSet = [NSCharacterSet lowercaseLetterCharacterSet];
if ([lowerCaseCharSet characterIsMember:character]) return 6;
return 7;
}

Filter NSMutableArray based on dictionary key

I have array with multiple dictionarys. which contains different keys . here i have goalType each goal contains number of records i want to filter the records based on goalType . please check the format below.
Array==>( {
goalType = 1;
languagetype = 1;
soundid = 19;
status = 1;
},
{
goalType = 1;
languagetype = 1;
soundid = 20;
status = 1;
},
{
goalType = 2;
languagetype = 1;
soundid = 21;
status = 1;
},
{
goalType = 2;
languagetype = 1;
soundid = 22;
status = 1;
},
{
goalType = 2;
languagetype = 1;
soundid = 23;
status = 1;
},
)
i have wrote the below code but filtered array getting empty
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"goalType == %# && languagetype == %d && status == 1 && soundid <= 3884",
[NSNumber numberWithInt:goalType.integerValue],languageid];
[dataSource predicate];
why not use
NSArray's filteredArrayUsingPredicate:
Evaluates a given predicate against each object in the receiving array and returns a new array containing the objects for which the predicate returns true.
I don't know of a
[NSArray predicate]
selector.I'm surprised that your not getting NoMethodFound exception.
NSDictionary *theDict = #{#"goalType":#(1),#"languagetype":#(1),#"soundid":#(19),#"status":#(1)};
NSDictionary *theDict1 = #{#"goalType":#(1),#"languagetype":#(1),#"soundid":#(20),#"status":#(1)};
NSDictionary *theDict2 = #{#"goalType":#(2),#"languagetype":#(1),#"soundid":#(21),#"status":#(1)};
NSDictionary *theDict3 = #{#"goalType":#(2),#"languagetype":#(1),#"soundid":#(23),#"status":#(1)};
NSMutableArray *testArray = [NSMutableArray array];
[testArray addObject:theDict];
[testArray addObject:theDict1];
[testArray addObject:theDict2];
[testArray addObject:theDict3];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"goalType == %# && languagetype == %# && status = 1 && soundid <= 3884", [NSNumber numberWithInt:1],[NSNumber numberWithInt:1]];
NSArray *filteredArray = [testArray filteredArrayUsingPredicate:predicate];
NSLog(#"%#",filteredArray);
This is the code works.

Find the highest repeated character in string and the count of the repeated character

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...
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.
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.
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 :)
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.

Resources