returning 8 closest cgfloat from a table lookup based on a cgfloat - iphone

I am trying to create this method. Let's call this
-(NSMutableArray*) getEightClosestSwatchesFor:(CGFloat)hue
{
NSString *myFile = [[NSBundle mainBundle] pathForResource:#"festival101" ofType:#"plist"];
NSMutableArray* myArray = [NSArray arrayWithContentsOfFile:myFile];
for (NSDictionary *dict in myArray)
{
NSLog(#"[plistData valueForKey:aKey] string] is %f", [[dict valueForKey:#"hue"] floatValue]) ;
}
return myArray;
}
pretty much, I am passing a cgfloat to this method which then needs to check a plist file which have hue key for 100 elements. I need to compare my hue with all of the hues and get 8 most closest hue and finally wrap these into an array and return this.
What would be most efficient way of doing this? Thanks in advance.

Here's my method if anyone is interested. Feel free to comment on it.
-(NSArray*)eightClosestSwatchesForHue:(CGFloat)hue
{
NSMutableArray *updatedArray = [[NSMutableArray alloc] initWithCapacity:100];
NSString *myFile = [[NSBundle mainBundle] pathForResource:#"festival101" ofType:#"plist"];
NSMutableArray* myArray = [NSArray arrayWithContentsOfFile:myFile];
for (NSDictionary *dict in myArray)
{
CGFloat differenceHue = fabs(hue - [[dict valueForKey:#"hue"] floatValue]);
//create a KVA for the differenceHue here and then add it to the dictionary and add this dictionary to the array.
NSDictionary* tempDict = [NSDictionary dictionaryWithObjectsAndKeys:
[dict valueForKey:#"id"], #"id",
[NSNumber numberWithFloat:differenceHue], #"differenceHue",
[dict valueForKey:#"color"], #"color",
nil];
[updatedArray addObject:tempDict];
}
//now we have an array of dictioneries with values we want. we need to sort this from little to big now.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"differenceHue" ascending:YES];
[updatedArray sortUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
[descriptor release];
//now get the first 8 elements and get rid of the remaining.
NSArray *finalArray = [updatedArray subarrayWithRange:NSMakeRange(0,8)];
[updatedArray release];
return finalArray;
}

Related

How to compare two MutableArrays and display the unmatched value in iphone? [duplicate]

This question already has answers here:
Compare 2 nsmutablearray and get different object to third array in ios
(4 answers)
Closed 9 years ago.
I have two MutableArray values like.
NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:#"Apple", #"Orange", #"Grapes", #"Banana", nil];
NSMutableArray *array1=[[NSMutableArray alloc]initWithObjects:#"Apple", #"Orange", #"Grapes", nil];
Now i have to compare that two Mutable arrays and display that unmatched object "Banana" into one string.
I am fresher to iOS so, anybody would send me the code for that problem.
Thanks in Advance.
As others have suggest, NSSet is probably your best bet. However, given that *array is mutable, you could simply remove the objects from it contained in *array1
NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:#"Apple", #"Orange", #"Grapes", #"Banana", nil];
NSMutableArray *array1=[[NSMutableArray alloc]initWithObjects:#"Apple", #"Orange", #"Grapes", nil];
[array removeObjectsInArray:array1];
NSLog(#"array: %#", array); // array: ( Banana )
// if you require result as a string
NSString *objectsAsString = [array componentsJoinedByString:#", "];
NSLog(#"objects as string: %#", objectsAsString); // objects as string: Banana
for(int i=0;i<[array count];i++)
{
NSString *str1 = [array objectAtIndex:i];
for(int j=0;j<[array1 count];j++)
{
NSString *str2 = [array1 objectAtIndex:j];
if([str1 isEqualToString:str2])
{
//do something which you want i.e add the values to some other array
}
}
}
You should probably use NSSet for this purpose
NSSet *set1 = [NSSet setWithObjects:#"a", #"s", #"d", #"f", nil];
NSSet *set2 = [NSSet setWithObjects:#"a", #"s", nil];
NSMutableSet *notInSet1 = [NSMutableSet setWithSet:set2];
[notInSet1 minusSet:set1];
NSMutableSet *notInSet2 = [NSMutableSet setWithSet:set1];
[notInSet2 minusSet:set2];
NSMutableSet *symmetricDifference = [NSMutableSet setWithSet:notInSet1];
[symmetricDifference unionSet:notInSet2];
NSArray *array1 = [[NSArray alloc] initWithObjects:#"a",#"b",#"c",nil];
NSArray *array2 = [[NSArray alloc] initWithObjects:#"a",#"d",#"c",nil];
NSMutableArray *ary_result = [[NSMutableArray alloc] init];
NSMutableArray *ary_resultUnmatched = [[NSMutableArray alloc] init];
for(int i = 0;i<[array1 count];i++)
{
for(int j= 0;j<[array2 count];j++)
{
if([[array1 objectAtIndex:i] isEqualToString:[array2 objectAtIndex:j]])
{
[ary_result addObject:[array1 objectAtIndex:i]];
} else {
[ary_resultUnmatched addObject:[array1 objectAtIndex:i]];
}
}
}
NSLog(#"%#",ary_result);//it will print a,c
NSLog(#"%#",ary_resultUnmatched);//it will print b,d
so in else condition you'll have your un matched values

How to join an NSArray output to an NSString separated with commas

I'm using the following code to try to join the array output into an NSString.
NSArray *array1 = [NSArray arrayWithObjects:[item objectForKey:#"id"], nil];
NSString *joinedString = [array1 componentsJoinedByString:#","];
NSLog(#"joinedString is %#", joinedString);
I would like this to output the joined string as: joined string is 55,56,57,66,88... etc... at the moment the output is:
2013-03-05 13:13:17.052 [63705:907] joinedString is 55
2013-03-05 13:13:17.056 [63705:907] joinedString is 56
2013-03-05 13:13:17.060 [63705:907] joinedString is 57
2013-03-05 13:13:17.064 [63705:907] joinedString is 66
You are probably running the join method inside a loop.
I suppose this is what you want.
NSMutableArray * array1 = [NSMutableArray array]; // create a Mutable array
for(id item in items){
[array1 addObject:[item objectForKey:#"id"]]; // Add the values to this created mutable array
}
NSString *joinedString = [array1 componentsJoinedByString:#","];
NSLog(#"joinedString is %#", joinedString);
You can do it as,
take for example
NSArray *array=#[#"A",#"B",#"C"];
NSString *string=[array componentsJoinedByString:#","];
NSLog(#"%#",string);
Output is :
A,B,C
What ever you are writing that one correct may be problem in [item objectForKey:#"id"] once check this one other all are fine.
NSMutableArray *array = [[NSMutableArray alloc]
initWithObjects:#"55",#"56",#"57",#"58", nil];
NSString *joinedString = [array componentsJoinedByString:#","];
NSLog(#"%#",joinedString);
I have been commenting on a couple of the answers here and found that most of the answers are just giving the code provided as the answer to solve this code, and the reason for that is because the code provided (See Provided code) works perfectly fine.
(Provide by question asker)
NSArray *array1 = [NSArray arrayWithObjects:[item objectForKey:#"id"], nil];
NSString *joinedString = [array1 componentsJoinedByString:#","];
NSLog(#"joinedString is %#", joinedString);
As the user hasn't provided how the item NSDictionary is created I am assuming that an NSArray has been created which contains some NSDictionaries
NSArray *array = [[NSArray alloc] initWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:#"55", #"id", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"65", #"id", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"75", #"id", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"65", #"id", nil],
nil];
The problem is with the code that hasn't been provide, because we know that item is an NSDictionary we know that [item objectForKey:#"id"] doesn't return an individual items it returns an NSArray of ids. So based on if it was an NSArray it would log something like joinedString is (55, 56, 57...)". We also know that it can't just be a string as we would also only have one value than so it would log some thing like this joinedString is 55, and again this isn't what is wanted so. the only way to get what has been provided would be to have something like this
for(NSDictionary *item in array) {
NSArray *array1 = [NSArray arrayWithObjects:[item objectForKey:#"id"], nil];
NSString *joinedString = [array1 componentsJoinedByString:#","];
NSLog(#"joinedString is %#", joinedString);
}
So if this is the case than the way to resolve this would be to do
NSMutableArray *array1 = [NSMutableArray array];
for(NSDictionary *item in array) {
[array1 addObject:[item objectForKey:#"id"]];
}
// Note that this doesn't need to be in a for loop `componentsJoinedByString:` only needs to run once.
NSString *joinedString = [array1 componentsJoinedByString:#","];
NSLog(#"joinedString is %#", joinedString);
The output of this would be (As user wants)
joinedString is 55,65,75,65
Once the question asker provides the missing code I will correct his to answer based on there code but until then I am assuming.
EDIT:
First Check [item objectForKey:#"id"] it is proper or not ??
And Then use following code :
NSArray *array1 = [NSArray arrayWithObjects:[item objectForKey:#"id"], nil];
NSString *commaSpStr;
commaSpStr = [array1 componentsJoinedByString:#", "];
NSLog(#"%#", commaSpStr);
You are recreating array1 everytime. Create an instance variable of array1, insert [item objectForKey:#"id"] value to it and you will see joinedString will be updated.
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (NSDictionary *item in array) {
[arr addObject:[item objectForKey:#"id"]];
}
NSString *joinedStr = [arr componentsJoinedByString:#","];

EXC_BAD_ACCESS on NSMutableDictionary

I am beginning with iOS development, I have this code :
First of all I declare the listOfItems NSMutableArray:
#interface SAMasterViewController () {
NSMutableArray *listOfItems;
}
#end
And now, here is the part the code that gives me an "EXC_BAD_ACCESS (code=1, address=0x5fc260000)" error.
The error is given in the last line of the "individual_data" object.
listOfItems = [[NSMutableArray alloc] init];
for(NSDictionary *tweetDict in statuses) {
NSString *text = [tweetDict objectForKey:#"text"];
NSString *screenName = [[tweetDict objectForKey:#"user"] objectForKey:#"screen_name"];
NSString *img_url = [[tweetDict objectForKey:#"user"] objectForKey:#"profile_image_url"];
NSInteger unique_id = [[tweetDict objectForKey:#"id"] intValue];
NSInteger user_id = [[[tweetDict objectForKey:#"user"] objectForKey:#"id"] intValue ];
NSMutableDictionary *individual_data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
text, #"text_tweet",
screenName,#"user_name",
img_url, #"img_url",
unique_id, #"unique_id",
user_id, #"user_id", nil];
[listOfItems addObject:individual_data];
}
Thanks in advance.
You can not put NSIntegers or any other non Objective-C class inside of an array or dictionary. You need to wrap them in an NSNumber.
NSMutableDictionary *individual_data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
text, #"text_tweet",
screenName,#"user_name",
img_url, #"img_url",
[NSNumber numberWithInteger:unique_id], #"unique_id",
[NSNumber numberWithInteger:user_id], #"user_id", nil];
//Or if you want to use literals
NSMutableDictionary *individual_data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
text, #"text_tweet",
screenName,#"user_name",
img_url, #"img_url",
#(unique_id), #"unique_id",
#(user_id), #"user_id", nil];

Crazy array sorting in tableView! sortedArrayUsingSelector help?

My tableView app loads the data into the table view.
Everything works perfectly, but the array sorting is kind of messed, like you can see in the picture below. I thought about using the sortedArrayUsingSelector, to straighten things up, but I'm not sure which "sorting method" I should use.
How can I sort this so the cells are sorted according the numbers? Like the order would be 1. 2. 3. 4. 5. etc NOT 1. 10. 11. 12. 13. 14. 2. 3. ?
Thanks a lot in advance!!
And a two-liner:
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES comparator:^(id obj1, id obj2) { return [obj1 compare:obj2 options:NSNumericSearch]; }];
rowTitleArray = [rowTitleArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
Sorry for this convoluted approach, but this does work...
NSArray *rowTitleArray = [[NSArray alloc] initWithObjects:
#"10. Tenth",
#"15. Fifteenth",
#"13. Thirteenth",
#"1. First",
#"2. Second",
#"22. TwentySecond", nil];
NSMutableArray *dictionaryArray = [NSMutableArray array];
for (NSString *original in rowTitleArray) {
NSString *numberString = [[original componentsSeparatedByString:#"."] objectAtIndex:0];
NSNumber *number = [NSNumber numberWithInt:[numberString intValue]];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
number, #"number", original, #"rowTitle", nil];
[dictionaryArray addObject:dict];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"number" ascending:YES];
NSArray *sortedDictionaryArray = [dictionaryArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:descriptor]];
NSMutableArray *sortedRowTitles = [NSMutableArray array];
for (NSDictionary *dict in sortedDictionaryArray) {
[sortedRowTitles addObject:[dict objectForKey:#"rowTitle"]];
}
rowTitleArray = [NSArray arrayWithArray:sortedRowTitles];
NSLog(#"%#", rowTitleArray);
Output:
"1. First",
"2. Second",
"10. Tenth",
"13. Thirteenth",
"15. Fifteenth",
"22. TwentySecond"
I will try to think of a more elegant solution.
Here is a more elegant solution:
NSInteger intSort(id num1, id num2, void *context) {
NSString *n1 = (NSString *) num1;
NSString *n2 = (NSString *) num2;
n1 = [[n1 componentsSeparatedByString:#"."] objectAtIndex:0];
n2 = [[n2 componentsSeparatedByString:#"."] objectAtIndex:0];
if ([n1 intValue] < [n2 intValue]) {
return NSOrderedAscending;
}
else if ([n1 intValue] > [n2 intValue]) {
return NSOrderedDescending;
}
return NSOrderedSame;
}
rowTitleArray = [rowTitleArray sortedArrayUsingFunction:intSort context:NULL];

Objective-c Sort Key array within array

Assuming I have an NSMutableArray which is loaded from file:
searchTermsArray = [[NSMutableArray alloc] initWithContentsOfFile: yourArrayFileName];
inside this array items are key objects
for (int i=0; i<[searchTermsArray count]; i++) {
NSLog(#"for array item %d: %# - %#",i,[[searchTermsArray objectAtIndex:i] objectForKey:#"title"], [[searchTermsArray objectAtIndex:i] objectForKey:#"theCount"] );
}
(which means that each array element (item) has 2 keys values:
searchTermsArray[0] = title (string) , theCount (also a string, but made out of integers)
Question: how should I sort "searchTermsArray" array from higher to lower based on "theCount" value?
(I am looking at the following code but it is not fitting the structure/syntax)
NSSortDescriptor *Sorter = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:NO];
[searchTermsArray sortUsingDescriptors:[NSArray arrayWithObject:Sorter]];
[Sorter release];
Shouldn't you be sorting based on theCount key?
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey:#"theCount" ascending:NO];
[searchTermsArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
I am not sure if there is a better way to do so. But this thing works.
NSInteger intSort(id param1, id param2, void *context) {
NSDictionary *dict1 = (NSDictionary *)param1;
NSDictionary *dict2 = (NSDictionary *)param2;
NSInteger dict1KeyCount = [[dict1 objectForKey:#"count"] intValue];
NSInteger dict2KeyCount = [[dict2 objectForKey:#"count"] intValue];
if (dict1KeyCount < dict2KeyCount) {
return NSOrderedAscending;
}else if (dict1KeyCount > dict2KeyCount) {
return NSOrderedDescending;
}else {
return NSOrderedSame;
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:#"two", #"title", #"2", #"count", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"three", #"title", #"3", #"count", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"one", #"title", #"1", #"count", nil], nil];
NSArray *sortedArray = [array sortedArrayUsingFunction:intSort context:NULL];
for (NSDictionary *dict in sortedArray) {
NSLog(#"%d", [[dict objectForKey:#"count"] intValue]);
}
[super viewDidLoad];
}
The NSSortDescriptor is usually used to sort objects of a class. You pass the name of the property in that class to be compared with others.
Since what you have in your array actually seems to be a NSDictionary, the NSSortDescriptor might not be the best way to approach this problem. Besides, your objects in the dictionary must have a type, so I would try to sort the array myself in one of the classic methods if I were you.