How do I alphabetically sort a custom object field within a NSMutable Array? - objective-c

I have a custom object like:
#import <Foundation/Foundation.h>
#interface Store : NSObject{
NSString *name;
NSString *address;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *address;
#end
I have an array of NSMutableArray (storeArray) containing Store objects:
store1 = [[Store alloc] init];
store1.name = #"Walmart";
store1.address = #"walmart address here..";
store2 = [[Store alloc] init];
store2.name = #"Target";
store2.address = #"Target address here..";
store3 = [[Store alloc] init];
store3.name = #"Apple Store";
store3.address = #"Apple store address here..";
//add stores to array
storeArray = [[NSMutableArray alloc] init];
[storeArray addObject:store1];
[storeArray addObject:store2];
[storeArray addObject:store3];
My question is how can I sort the array by the store name? I know I can sort an array alphabetically by using this line:
[nameOfArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
How can I apply this to the store name of my Store class?

NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(caseInsensitiveCompare:)];
[nameOfArray sortedArrayUsingDescriptors:#[sortDescriptor]];
Related documentation:
[NSArray sortedArrayUsingDescriptors:]
NSSortDescriptor

Regexident's answer is based on NSArrays, the corresponding in-place sorting for NSMutableArray would be -sortUsingDescriptors:
[storeArray sortUsingDescriptors:
[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(caseInsensitiveCompare:)]]];
Now storeArray it-self will be sorted.

Related

Filter NSArray of Object with NSArray of NSNumber with NSPredicate

i'm trying to filer an array of this Object:
MyObject.h
#interface MyObject : NSObject
#property (assign) int id_object;
#property (nonatomic, strong) NSString *name;
#end
So for example in my firstArray i have some MyObject:
MyObject *ob1 = [[MyObject alloc] init];
[ob1 setId_Object:1;
[ob1 setName:#"Carl"];
MyObject *ob2 = [[MyObject alloc] init];
[ob2 setId_Object:2;
[ob2 setName:#"Carl"];
MyObject *ob3 = [[MyObject alloc] init];
[ob3 setId_Object:3;
[ob3 setName:#"Carl"];
NSArray *firstArray = [[NSArray alloc] initWithObjects:ob1,ob2,ob3,nil];
then i want filter this array with NSPredicate with an array of NSNumber, like this:
NSArray *secondArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],nil];
i have tried this:
NSArray *filteredObject = [firstArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"id_object IN %#",secondArray]];
but the filteredObject is empty, how i can do?
Seems to be your test case that is wrong. I don't think your setId_object does what you think it does when calling it with an NSNumber;
[ob1 setId_object:[NSNumber numberWithInt:1]];
NSLog(#"%d", ob1.id_object);
> 391
[ob1 setId_object:1];
NSLog(#"%d", ob1.id_object);
> 1
Replacing the initializations makes your test case run ok.
EDIT: My test case, cut'n'pasted;
MyObject *ob1 = [[MyObject alloc] init]; ob1.id_object = 1; [ob1 setName:#"Carl"];
MyObject *ob2 = [[MyObject alloc] init]; ob2.id_object = 2; [ob2 setName:#"Carl"];
MyObject *ob3 = [[MyObject alloc] init]; ob3.id_object = 3; [ob3 setName:#"Carl"];
NSArray *firstArray = [[NSArray alloc] initWithObjects:ob1,ob2,ob3,nil];
NSArray *secondArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],nil];
NSArray *filteredObject = [firstArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"id_object IN %#",secondArray]];
NSLog(#"%#", filteredObject);
>>> <MyObject: 0x100110350> {1,"Carl"}
>>> <MyObject: 0x1001104b0> {2,"Carl"}
once check this one,
NSArray *filteredObject = [questionSections filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.Carl contains %# OR self.Carl contains %# ",#"1",#"2"]];
EX:-
NSArray* questionSections=[[NSArray alloc] initWithObjects:[[NSDictionary alloc] initWithObjectsAndKeys:
#"List 3 rooms in your house?",#"name",#"301q.png",#"questionpicture",nil],[[NSDictionary alloc] initWithObjectsAndKeys:#"Name a commonbird?",#"name",#"202q.png",#"questionpicture",nil], nil];
NSArray *filteredObject = [questionSections filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self.questionpicture contains %# OR self.questionpicture contains %# ",#"2",#"3"]];
NSLog(#"%#",filteredObject);
O/P:--
(
{
name = "List 3 rooms in your house?";
questionpicture = "301q.png";
},
{
name = "Name a common bird?";
questionpicture = "202q.png";
}
)
try replace
#property (nonatomic, copy) NSNumber* id_object;
#property (nonatomic, copy) NSString *name;
instead of
#property (assign) int id_object;
#property (nonatomic, strong) NSString *name;

Default list in Objective C?

I want to store data at run time, I can have a linked list and add at runtime, however as I am new to IOS and objective C, do we have any default list in which we can add our datas, (Datas are two stings and an integer).
Cocoa provides NSArray and NSMutableArray, a pair of ordered containers similar to Java's ArrayList and C#'s List. You can add values to NSMutableArray, and it will grow as you add more elements; NSArray is read-only.
You can use .plist files to store your data.
Read more 'Loading data from .plist files', 'How to use plist in iphone?' or google it like 'load data from .plist'. However you can create NSArray or something like this at run time. If you want dive deeper you must read ObjC Collections Programming Topics
Make a class for your data with default properties and make sure it inherits NSObject then use NSMUtableArray to add/remove elements to the list.
// in the .h file of your object
#interface MyObject : NSObject {
NSString* strAttribute1;
// add more attributes as you want
}
#property (nonatomic, retain) NSString* strAttribute1;
#end
// then in the .m file
// do not forget the #import ""
#implement MyObject
#synthesize strAttribute1;
// override the dealloc to release the retained objects
#end
then in your code where you want to make a list of this object
NSMutableArray* myArray = [[NSMutableArray alloc] init];
// add elements and iterate through them
// do not forgot to free the memory if you are not using ARC
[myArray release];
You can use NSArray or NSMutableArray or NSDictionary or NSMutableDictionary depending on your needs.
NSArray:
NSArray *myArray;
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
NSString *aString = #"a string";
myArray = [NSArray arrayWithObjects:aDate, aValue, aString, nil];
NSMutableArray:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
NSString *aString = #"a string";
[myArray addObject:aDate];
[myArray addObject:aValue];
[myArray addObject:aString];
NSDictionary:
NSDictionary * myDict = [NSDictionary dictionaryWithObjects:aDate, aValue, aString forKeys:firstDate, firstValue, firstString];
NSMutableDictionary:
NSString *aString = #"a string";
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
myDict = [[NSMutableDictionary alloc] init];
[myDict setObject:aString forKey:firstString];
[myDict setObject:aDate forKey:firstDate];
[myDict setObject:aValue forKey:firstValue];

Sort NSMutableArray Of multiple Objects without keys

I have a NSMutableArray of objects, below is the struct:
//object at index i
locations {
NSString* address;
NSString* state;
NSNumber* distance;
}
I have 10000 object like the above structure in the NSMutableArray.
How do order this array so that the locations are in order by the NSNumber distance?
I tried this:
lowToHigh = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
[locationArray sortUsingDescriptors:[NSArray arrayWithObject:lowToHigh]];
is using the sortDescriptorWithKey:#"distance" wrong? since distance isn't actually a key, it NSNumber* distance.
edit in my header #property (strong, nonatomic)NSNumber* _distance; and then #synthesize _distance = distance; in my methods file but this is in locationObjects.* object class. Then I import this in my current class I am doing this sorting. Is that an issue?
How I import is locationObjects* locObj = [[locationObjects alloc] init];
This is what I use:
NSSortDescriptor *lowToHigh = [[NSSortDescriptor alloc] initWithKey:#"distance"
ascending:YES];
NSArray *mySortDescriptors = [NSArray arrayWithObject:lowToHigh];
NSArray *sortedArray = [locationArray sortedArrayUsingDescriptors:mySortDescriptors];

Sorting and matching

NSMutableArray *full_text_list = [[NSMutableArray alloc]init];
[full_text_list addObject:#"for"];
[full_text_list addObject:#"for your information"];
[full_text_list addObject:#"you"];
[full_text_list addObject:#"at"];
NSMutableArray *short_text_list = [[NSMutableArray alloc]init];
[short_text_list addObject:#"4"];
[short_text_list addObject:#"fyi"];
[short_text_list addObject:#"u"];
[short_text_list addObject:#"#"];
i dont want to sort the second array. i want to get the appropriate element based on index.
I want to sort only the full_text_list array based on length, so i tried a below
NSSortDescriptor * descriptors = [[[NSSortDescriptor alloc] initWithKey:#"length"
ascending:NO] autorelease];
NSArray * sortedArray = [full_text_list sortedArrayUsingDescriptors:
[NSArray arrayWithObject:descriptors]];
and the above code works fine.But i am not sure how to match short_text_list array with new sorted array
So when doing like [full_text_list objectatindex:0] and [short_text_list objectatindex:0] will not match
result would be "for your information" and "for" but the result should be "for your information" and "fyi"
Please let me know
How should it match? You have two arrays and are just sorting one and expect the second one automagically gets sorted too? This can not work. Why don't you just build a dictionary with the long information as key and the short one as value or vs?
A second way to do this would be:
// Create your two arrays and then combine them into one dictionary:
NSDictionary *textDict = [NSDictionary dictionaryWithObjects:short_text_list
forKeys:full_text_list];
// Create your sorted array like you did before:
NSSortDescriptor * descriptors = [[[NSSortDescriptor alloc] initWithKey:#"length" ascending:NO] autorelease];
NSArray * sortedArray = [full_text_list sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptors]];
// Then to access short_text, you would use:
NSString *object0ShortText = [textDict objectForKey:[sortedArray objectAtIndex:0]];
I would create a new class which contains both values and insert that into the array instead of creating the two separate array's in the first place:
#interface TextList : NSManagedObject
#property (nonatomic, retain) NSString *full_text;
#property (nonatomic, retain) NSString *short_text;
- (TextList *)initWithFullText:(NSString *)full_text shortText:(NSString *)short_text;
#end
Create your .m file, and then when you want to use it, use something like:
NSMutableArray *full_text_list = [[NSMutableArray alloc]init];
[full_text_list addObject:[TextList initWithFullText:#"for" shortText:#"4"]];
[full_text_list addObject:[TextList initWithFullText:#"for your information" shortText:#"fyi"]];
[full_text_list addObject:[TextList initWithFullText:#"you" shortText:#"u"]];
[full_text_list addObject:[TextList initWithFullText:#"at" shortText:#"#"]];
Then perform the sort:
NSSortDescriptor * descriptors = [[[NSSortDescriptor alloc] initWithKey:#"full_text.length" ascending:NO] autorelease];
NSArray * sortedArray = [full_text_list sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptors]];
Now you can do [[sortedArray objectAtIndex:0] full_text]; and [[sortedArray objectAtIndex:0] short_text]; or
TextList *txtList = [sortedArray objectAtIndex:0];
// txtList.full_text and txtList.short_text are both valid.

Objective-C : Sorting NSMutableArray containing NSMutableArrays

I'm currently using NSMutableArrays in my developments to store some data taken from an HTTP Servlet.
Everything is fine since now I have to sort what is in my array.
This is what I do :
NSMutableArray *array = [[NSMutableArray arrayWithObjects:nil] retain];
[array addObject:[NSArray arrayWithObjects: "Label 1", 1, nil]];
[array addObject:[NSArray arrayWithObjects: "Label 2", 4, nil]];
[array addObject:[NSArray arrayWithObjects: "Label 3", 2, nil]];
[array addObject:[NSArray arrayWithObjects: "Label 4", 6, nil]];
[array addObject:[NSArray arrayWithObjects: "Label 5", 0, nil]];
First column contain a Label and 2nd one is a score I want the array to be sorted descending.
Is the way I am storing my data a good one ? Is there a better way to do this than using NSMutableArrays in NSMutableArray ?
I'm new to iPhone dev, I've seen some code about sorting but didn't feel good with that.
Thanks in advance for your answers !
This would be much easier if you were to create a custom object (or at least use an NSDictionary) to store the information, instead of using an array.
For example:
//ScoreRecord.h
#interface ScoreRecord : NSObject {
NSString * label;
NSUInteger score;
}
#property (nonatomic, retain) NSString * label;
#property (nonatomic) NSUInteger score;
#end
//ScoreRecord.m
#import "ScoreRecord.h"
#implementation ScoreRecord
#synthesize label, score;
- (void) dealloc {
[label release];
[super dealloc];
}
#end
//elsewhere:
NSMutableArray * scores = [[NSMutableArray alloc] init];
ScoreRecord * first = [[ScoreRecord alloc] init];
[first setLabel:#"Label 1"];
[first setScore:1];
[scores addObject:first];
[first release];
//...etc for the rest of your scores
Once you've populated your scores array, you can now do:
//the "key" is the *name* of the #property as a string. So you can also sort by #"label" if you'd like
NSSortDescriptor * sortByScore = [NSSortDescriptor sortDescriptorWithKey:#"score" ascending:YES];
[scores sortUsingDescriptors:[NSArray arrayWithObject:sortByScore]];
After this, your scores array will be sorted by the score ascending.
You don't need to create a custom class for something so trivial, it's a waste of code. You should use an array of NSDictionary's (dictionary in ObjC = hash in other languages).
Do it like this:
NSMutableArray * array = [NSMutableArray arrayWithObjects:
[NSDictionary dictionaryWithObject:#"1" forKey:#"my_label"],
[NSDictionary dictionaryWithObject:#"2" forKey:#"my_label"],
[NSDictionary dictionaryWithObject:#"3" forKey:#"my_label"],
[NSDictionary dictionaryWithObject:#"4" forKey:#"my_label"],
[NSDictionary dictionaryWithObject:#"5" forKey:#"my_label"],
nil];
NSSortDescriptor * sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"my_label" ascending:YES] autorelease];
[array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];