Sort NSArray by 'Date' Element of included NSDictionaries - objective-c

Here's what I have:
An NSMutableArray that holds several NSDictionary Objects.
Each NSDictionary has a Date String as an Element.
Here's my loop that prints out the Date in each NSDictionary
[dateFormatterIn setDateFormat:#"yyyyMMddHHmmss\n"];
[dateFormatterOut setDateFormat:#"dd.MM.yyyy"];
for(NSMutableDictionary *thisStory in stories){
id fromDate = [thisStory objectForKey:#"from_time"];
id date = [dateFormatterIn dateFromString:fromDate];
NSLog(#"%#", [dateFormatterOut stringFromDate:date]);
}
Does anyone have a clue how I can sort my array stories by date?
I am quite new to objective C.
Thanks in advance!

Using the your stories array's sortUsingDescriptor method should do the trick:
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey: #"from_time" ascending: YES] autorelease];
[stories sortUsingDescriptors: [NSArray arrayWithObject: sortDescriptor]];

Let's assume Following data structure : array variable name: collectionArray =
[
{
date: "01-02-2015 02:01",
value: 1,
name: "rajan"
},
{
date: "01-02-2014 02:01",
value: 11,
name: "rajan1"
},
{
date: "01-02-2012 02:01",
value: 111,
name: "rajan2"
}
]
Now to sort this array of nsdictionary by date we follow the following steps
`NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy HH:mm"];
NSMutableArray *sortedArray = [[collectionArray sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *d1Str =[obj1 valueForKey:#"date"];
NSString *d2Str =[obj2 valueForKey:#"date"]
NSString *d1Timestamp = [NSString stringWithFormat:#"%f", [[formatter dateFromString:d1Str] timeIntervalSince1970]];
NSString *d2Timestamp = [NSString stringWithFormat:#"%f", [[formatter dateFromString:d2Str] timeIntervalSince1970]];
return [d2Timestamp compare:d1Timestamp options:NSNumericSearch]; // descending order
}] mutableCopy];`

Related

How to sort NSDictionary using millisecond (Time format)?

I have a Dictionary of format [Int:Any] I have bunch of key value pairs in it. I want to sort out the dictionary using the millisecond time format
[169887: ["noti_type": 0, "project_name": "Design Project", "eventCount": 6, "author_pic": " /file/download/profile$2348d4f21095a01cc16a8ad9bf08f966.jpg", "canvas_name": "Design Reference #31 : Windows in NYC", "lastUpdatedAt": 1513585053629, "author_name": "Jake Kyung "],
173865: ["noti_type": 0, "project_name": "BeeCanvas DEV", "eventCount": 13, "author_pic": " &&&& /file/download/profile$80bbc9731a859d4e083df0df8044bcde.jpg &&&& /file/download/profile$2348d4f21095a01cc16a8ad9bf08f966.jpg", "canvas_name": "Android Release note", "lastUpdatedAt": 1513307315308, "author_name": " &&&& Sukho Bu &&&& Jake Kyung "]
I have a bunch of these kind of values in my Dictionary. I want to sort them using the lastUpdatedAt value which is 1513585053629 millisecond format.
I have gone through some posts which said this is possible if I can use a NSDate,
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey: #"dateOfInfo" ascending: NO];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
But I was just wondering if I could achieve this directly using the millisecond format instead of converting to NSDate ?
This is just demo for understanding..
NSMutableDictionary *dict1 = [[NSMutableDictionary alloc]init];
[dict1 setObject:#"Design Project" forKey:#"project_name"];
[dict1 setObject:#"1513585053629" forKey:#"lastUpdatedAt"];
NSMutableDictionary *dict2 = [[NSMutableDictionary alloc]init];
[dict2 setObject:#"BeeCanvas DEV" forKey:#"project_name"];
[dict2 setObject:#"1513307315308" forKey:#"lastUpdatedAt"];
NSMutableArray *arr = [[NSMutableArray alloc]init];
[arr addObject:dict1];
[arr addObject:dict2];
NSLog(#"original array = %#",arr);
you can give directly key name in sort descriptor.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey: #"lastUpdatedAt" ascending:YES];
NSArray *sortedArray = [arr sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSLog(#"sorted array = %#",sortedArray);
Output:-
sorted array = (
{
lastUpdatedAt = 1513307315308;
"project_name" = "BeeCanvas DEV";
},
{
lastUpdatedAt = 1513585053629;
"project_name" = "Design Project";
}
)

create a dictionary with an array of dictionaries

Noob here. I recently started working with objective C, and currently I am stuck with dictionary concept. I want to create a json object as shown below:
{"UserData": {
"Name": Mike Smith,
"Age": 32,
"category": [1,2,3],
"Weekly Data": [
{"Monday" : [1.0,2.0,3.0]},
{"Tuesday": [1.0,2.0,3.0]}
]
}
}
I wrote the following piece of code which doesn't give the desired result. I wonder if someone could help me.
-(NSString*)populateUserPreferences
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSMutableArray *categorydata = [[NSMutableArray alloc] init];
NSMutableArray *weeklydata = [[NSMutableArray alloc] init];
for (int i=0;i<4; i++)
{
[categorydata addObject:[NSNumber numberWithInt:i]];
}
NSMutableArray *mondaydata = [[NSMutableArray alloc] init];
for (int j=0; j<3; j++)
{
[mondaydata addObject:[NSNumber numberWithInt:j]];
}
NSMutableArray *tuesdaydata = [[NSMutableArray alloc] init];
for (int j=0; j<3; j++)
{
[tuesdaydata addObject:[NSNumber numberWithInt:j]];
}
NSDictionary *monday = [NSDictionary dictionaryWithObject:mondaydata];
NSDictionary *tuesday = [NSDictionary dictionaryWithObject:tuesdaydata];
[weeklydata addObject: monday ];
[weeklydata addObject: tuesday ];
}
[dict setObject:[NSString stringWithFormat:"Mike Smith"] forKey:#"Name"];
[dict setObject:[NSNumber numberWithInteger:32.0] forKey:#"Age"];
[dict setObject:categorydata forKey:#"category"];
[dict setObject:weeklydata forKey:#"Weekly Data"];
NSString * userdata = [dict JSONRepresentation];
NSLog(request);
NSDictionary *userdataJson = [NSDictionary dictionaryWithObject:dict forKey:#"userData"];
return [userdataJson JSONRepresentation];
}
Thanks in advance for looking into it.
Apoorva
The mistake is when creating the monday and tuesday dictionary.
// mondaydata & tuesday is just array.
NSDictionary *monday = [NSDictionary dictionaryWithObject:mondaydata];
NSDictionary *tuesday = [NSDictionary dictionaryWithObject:tuesdaydata];
This code is mistake since you did not assign the dictionary properly (where is the key for the dictionary?). Instead you should do:
NSDictionary *mondayDict = [[NSDictionary alloc] init];
[mondayDict setObject:mondaydata forKey:"Monday"];
NSDictionary *tuesdayDict = [[NSDictionary alloc] init];
[tuesdayDict setObject:tuesdaydata forKey:"Tuesday"];
Then you can add mondayDict and tuesdayDict to your array weeklydata.
ps. just a note, name your variable meaningfully. For example, mondaydata is not descriptive enough. You should use mondayArr for example. To easily identify it is an array. Just a normal coding practice to share.
NSDictionary * dict = #{#"UserData": #{
#"Name": #"Mike Smith",
#"Age": #32,
#"category": #[#1,#2,#3],
#"Weekly Data": #[
#{#"Monday" : #[#1.0,#2.0,#3.0]},
#{#"Tuesday": #[#1.0,#2.0,#3.0]}
]
}
};
NSError * error = nil;
NSData * data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
} else {
// Do what you want
}

Sort NSMutableArray based on strings from another NSArray

I have an NSArray of strings that I want to use as my sort order:
NSArray *permissionTypes = [NSArray arrayWithObjects:#"Read", #"Write", #"Admin", nil];
I then have a NSMutableArray that may or may not have all three of those permissions types, but sometimes it will only be 2, sometimes 1, but I still want it sorted based on my permissionsTypes array.
NSMutableArray *order = [NSMutableArray arrayWithArray:[permissions allKeys]];
How can I always sort my order array correctly based on my using the permissionTypes array as a key?
I would go about this by creating a struct or an object to hold the permission types.
Then you can have...
PermissionType
--------------
Name: Read
Order: 1
PermissionType
--------------
Name: Write
Order: 2
and so on.
Then you only need the actual array of these objects and you can sort by the order value.
[array sortUsingComparator:^NSComparisonResult(PermissionType *obj1, PermissionType *obj2) {
return [obj1.order compare:obj2.order];
}];
This will order the array by the order field.
NSMutableArray *sortDescriptors = [NSMutableArray array];
for (NSString *type in permissionTypes) {
NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:type ascending:YES] autorelease];
[sortDescriptors addObject:descriptor];
}
sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];
Use whichever sorting method on NSMutableArray you prefer, you will either provide a block or a selector to use for comparing two elements. In that block/selector rather than comparing the two strings passed in directly look each up in your permissionTypes array using indexOfObject: and compare the resulting index values returned.
I suggest you another approuch:
- (void)viewDidLoad
{
[super viewDidLoad];
arrayPermissions = [[NSMutableArray alloc] init];
NSDictionary *dicRead = [NSDictionary dictionaryWithObjectsAndKeys:
#"Read", #"Permission", nil];
NSDictionary *dicWrite = [NSDictionary dictionaryWithObjectsAndKeys:
#"Write", #"Permission", nil];
NSDictionary *dicAdmin = [NSDictionary dictionaryWithObjectsAndKeys:
#"Admin", #"Permission", nil];
NSLog(#"my dicRead = %#", dicRead);
NSLog(#"my dicWrite = %#", dicWrite);
NSLog(#"my dicAdmin = %#", dicAdmin);
[arrayPermissions addObject:dicRead];
[arrayPermissions addObject:dicWrite];
[arrayPermissions addObject:dicAdmin];
NSLog(#"arrayPermissions is: %#", arrayPermissions);
// create a temporary Dict again
NSDictionary *temp =[[NSDictionary alloc]
initWithObjectsAndKeys: arrayPermissions, #"Permission", nil];
// declare one dictionary in header class for global use and called "filteredDict"
self.filteredDict = temp;
self.sortedKeys =[[self.filteredDict allKeys]
sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sortedKeys is: %i", sortedKeys.count);
NSLog(#"sortedKeys is: %#", sortedKeys);
}
hope help

Sort NSMutableArray with strings that contain numbers?

I have a NSMutableArray and it has the users high scores saved into it. I want to arrange the items numerically (the numbers are stored in NSStrings.)Example:4,2,7,8To2,4,7,8What is the simplest way to do this if the data is stored in NSStrings?
This code will do it:
//creating mutable array
NSMutableArray *myArray = [NSMutableArray arrayWithObjects:#"4", #"2", #"7", #"8", nil];
//sorting
[myArray sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:(NSNumericSearch)];
}];
//logging
NSLog(#"%#", myArray);
It uses blocks, make sure your target OS supports that (It's 4.0 for iOS and 10.6 for OSX).
This code works. I tried it:
NSMutableArray *unsortedHighScores = [[NSMutableArray alloc] initWithObjects:#"4", #"2", #"7", #"8", nil];
NSMutableArray *intermediaryArray = [[NSMutableArray alloc] init];
for(NSString *score in unsortedHighScores){
NSNumber *scoreInt = [NSNumber numberWithInteger:[score integerValue]];
[intermediaryArray addObject:scoreInt];
}
NSArray *sortedHighScores = [intermediaryArray sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"%#", sortedHighScores);
The output is this:
2
4
7
8
If you have any questions about the code, just ask in the comments. Hope this helps!
The NSMutableArray method sortUsingSelector: should do it:
[scoreArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)]
should do it.
If the array is of nsdictionaries conaining numeric value for key number
isKeyAscending = isKeyAscending ? NO : YES;
[yourArray sortUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
NSString *str1 = [obj1 objectForKey:#"number"];
NSString *str2 = [obj2 objectForKey:#"number"];
if(isKeyAscending) { //ascending order
return [str1 compare:str2 options:(NSNumericSearch)];
} else { //descending order
return [str2 compare:str1 options:(NSNumericSearch)];
}
}];
//yourArray is now sorted
The answer from Darshit Shah make it smootly
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc]initWithKey:#"rank" ascending:YES selector:#selector(localizedStandardCompare:)];

Getting NSDictionary keys sorted by their respective values

I have an NSMutableDictionary with integer values, and I'd like to get an array of the keys, sorted ascending by their respective values. For example, with this dictionary:
mutableDict = {
"A" = 2,
"B" = 4,
"C" = 3,
"D" = 1,
}
I'd like to end up with the array ["D", "A", "C", "B"]. My real dictionary is much larger than just four items, of course.
The NSDictionary Method keysSortedByValueUsingComparator: should do the trick.
You just need a method returning an NSComparisonResult that compares the object's values.
Your Dictionary is
NSMutableDictionary * myDict;
And your Array is
NSArray *myArray;
myArray = [myDict keysSortedByValueUsingComparator: ^(id obj1, id obj2) {
if ([obj1 integerValue] > [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 integerValue] < [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
Just use NSNumber objects instead of numeric constants.
BTW, this is taken from:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Dictionaries.html
NSDictionary has this neat method called allKeys.
If you want the array to be sorted though, keysSortedByValueUsingComparator: should do the trick.
Richard's solution also works but makes some extra calls you don't necessarily need:
// Assuming myDictionary was previously populated with NSNumber values.
NSArray *orderedKeys = [myDictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){
return [obj1 compare:obj2];
}];
Here's a solution:
NSDictionary *dictionary; // initialize dictionary
NSArray *sorted = [[dictionary allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[dictionary objectForKey:obj1] compare:[dictionary objectForKey:obj2]];
}];
The simplest solution:
[dictionary keysSortedByValueUsingSelector:#selector(compare:)]
Here i have done something like this:
NSMutableArray * weekDays = [[NSMutableArray alloc] initWithObjects:#"Sunday",#"Monday",#"Tuesday",#"Wednesday",#"Thursday",#"Friday",#"Saturday", nil];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSMutableArray *dictArray = [[NSMutableArray alloc] init];
for(int i = 0; i < [weekDays count]; i++)
{
dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:i],#"WeekDay",[weekDays objectAtIndex:i],#"Name",nil];
[dictArray addObject:dict];
}
NSLog(#"Before Sorting : %#",dictArray);
#try
{
//for using NSSortDescriptor
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"WeekDay" ascending:YES];
NSArray *descriptor = #[sortDescriptor];
NSArray *sortedArray = [dictArray sortedArrayUsingDescriptors:descriptor];
NSLog(#"After Sorting : %#",sortedArray);
//for using predicate
//here i want to sort the value against weekday but only for WeekDay<=5
int count=5;
NSPredicate *Predicate = [NSPredicate predicateWithFormat:#"WeekDay <=%d",count];
NSArray *results = [dictArray filteredArrayUsingPredicate:Predicate];
NSLog(#"After Sorting using predicate : %#",results);
}
#catch (NSException *exception)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorting cant be done because of some error" message:[NSString stringWithFormat:#"%#",exception] delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert setTag:500];
[alert show];
[alert release];
}