NSArray sort arrays - objective-c

There are several NSArray objects in a NSArray.
Example code is like this
NSArray *a1 = #[#3, #3, #2];
NSArray *a2 = #[#2, #4, #5];
NSArray *a3 = #[#2, #5, #1];
NSArray *array = #[a1, a2, a3];
How do I sort a1, a2 and a3 in numerical/alphabetical/logical order?

Assuming that each array contains only instances of NSNumber this should work:
NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(NSArray *array1, NSArray *array2) {
NSString *str1 = [array1 componentsJoinedByString:#"|"];
NSString *str2 = [array2 componentsJoinedByString:#"|"];
return [str1 compare:str2];
}];
I doubt it'll be particularly efficient with larger data sets though.

Related

NSString to NSArray and editing every object

I have an NSString filled with objects seperated by a comma
NSString *string = #"1,2,3,4";
I need to seperate those numbers and store then into an array while editing them, the result should be
element 0 = 0:1,
element 1 = 1:2,
element 2 = 2:3,
element 3 = 3:4.
How can i add those to my objects in the string ??
Thanks.
P.S : EDIT
I already did that :
NSString *string = #"1,2,3,4";
NSArray *array = [string componentsSeparatedByString:#","];
[array objectAtIndex:0];//1
[array objectAtIndex:1];//2
[array objectAtIndex:2];//3
[array objectAtIndex:3];//4
I need the result to be :
[array objectAtIndex:0];//0:1
[array objectAtIndex:1];//1:2
[array objectAtIndex:2];//2:3
[array objectAtIndex:3];//3:4
In lieu of a built in map function (yey for Swift) you would have to iterate over the array and construct a new array containing the desired strings:
NSString *string = #"1,2,3,4";
NSArray *array = [string componentsSeparatedByString:#","];
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:array.count];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[newArray addObject:[NSString stringWithFormat:#"%lu:%#", (unsigned long)idx, obj]];
}];
The first thing you need to do is separate the string into an array of component parts - NSString has a handy method for that : '-componentsSeparatedByString'. Code should be something like this :
NSArray *components = [string componentsSeparatedByString:#","];
So that gives you 4 NSString objects in your array. You could then iterate through them to make compound objects in your array, though you arent exactly clear how or why you need those. Maybe something like this :
NSMutableArray *resultItems = [NSMutableArray array];
for (NSString *item in components)
{
NSString *newItem = [NSString stringWithFormat:#"%#: ... create your new item", item];
[resultItems addObject:newItem];
}
How about this?
NSString *string = #"1,2,3,4";
NSArray *myOldarray = [string componentsSeparatedByString:#","];
NSMutableArray *myNewArray = [[NSMutableArray alloc] init];
for (int i=0;i<myOldarray.count;i++) {
[myNewArray addObject:[NSString stringWithFormat:#"%#:%d", [myOldarray objectAtIndex:i], ([[myOldarray objectAtIndex:i] intValue]+1)]];
}
// now you have myNewArray what you want.
This is with consideration that in array you want number:number+1

Sorting JSON Data by date

Hi I'm getting data online from a JSON file and I'm trying to sort it by date in descending order, I've done it before using an XML parser using an RSS feed and tried to use the same concept but can't seem to get it and it crashes every time.
NSData *data = [NSData dataWithContentsOfURL:url];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSDictionary *dataDict = [dict objectForKey:#"data"];
NSArray *array = [dataDict objectForKey:#"items"];
for (int i=0; i<[array count]; i++) {
SongInfo *song = [[SongInfo alloc]init];
NSMutableDictionary *entry = [array objectAtIndex:i];
song.uploaded = [entry objectForKey:#"uploaded"];
song.uploader = [entry objectForKey:#"uploader"];
NSComparator comparator = ^(NSDictionary *a, NSDictionary *b) {
return [a[#"uploaded"] compare:b[#"uploaded"]];
};
NSUInteger index = [songsArray indexOfObject:entry
inSortedRange:NSMakeRange(0, [songsArray count])
options:NSBinarySearchingInsertionIndex
usingComparator:comparator];
[songsArray insertObject:song atIndex:index];
EDIT: Managed to fix it by using the NSSortDescriptor and putting it into an array and then back into the same array, not sure if there is a better way to do this but this is how I did it...
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"uploaded"
ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [songsArray sortedArrayUsingDescriptors:sortDescriptors];
songsArray = [NSMutableArray arrayWithArray:sortedArray];
// [songsArray addObject:[song copy] atIndex:index];
[songsArray addObject:song];
You're comparing objects inserted in the songsArray with a comparator that takes in two dictionaries. It seems like the comparator should compare SongInfo objects rather than NSDictionaries.
We can't see what songsArray is. Creating a sorted array manually like you do is really inefficient. Call the NSArray method sortedArrayUsingComparator instead, and there is no need to create SongInfo objects.
On the other hand, if an array of SongInfo* is what you want, create that array first as an NSMutableArray with all the SongInfo's from the JSON data, then sort that array by calling sortUsingComparator.
Note that in the comparator block you can actually use the type of the object: So in the first case NSDictionary* instead of id, in the second case SongInfo* instead of id.

Objective-C: Sort keys of NSDictionary based on dictionary entries

OK so I know that dictionaries can't be sorted. But, say I have NSMutableArray *keys = [someDictionary allKeys]; Now, I want to sort those keys, based on the corresponding values in the dictionary (alphabetically). So if the dictionary contains key=someString, then I want to sort keys based on the strings they correspond to. I think its some application of sortUsingComparator but its a little out of my reach at this point.
NSArray *keys = [someDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [someDictionary objectForKey:a];
NSString *second = [someDictionary objectForKey:b];
return [first compare:second];
}];
NSDictionary *dict = // however you obtain the dictionary
NSMutableArray *sortedKeys = [NSMutableArray array];
NSArray *objs = [dict allValues];
NSArray *sortedObjs = [objs sortedArrayUsingSelector:#selector(compare:)];
for (NSString *s in sortedObjs)
[sortedKeys addObjectsFromArray:[dict allKeysForObject:s]];
Now sortedKey will contain the keys sorted by their corresponding objects.
Sort keys of NSDictionary based on dictionary keys
Abobe is for returning a sorted array with based on dictionary content, this is for returning an array sorted by dictionary key:
NSArray *keys = [theDictionary allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
return [a compare:b];
}];
NSMutableArray *sortedValues = [NSMutableArray new];
for(NSString *key in sortedKeys)
[sortedValues addObject:[dictFilterValues objectForKey:key]];
Just write it here cause I didn't find it anywhere: To get an alphanumeric sorted NSDictionary back from an NSDictionary based on the value - which in my case was neccessary - you can do the following:
//sort typeDict alphanumeric to show it in order of values
NSArray *keys = [typeDict allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSString *first = [typeDict objectForKey:a];
NSString *second = [typeDict objectForKey:b];
return [first compare:second];
}];
NSLog(#"sorted Array: %#", sortedKeys);
NSMutableDictionary *sortedTypeDict = [NSMutableDictionary dictionary];
int counter = 0;
for(int i=0; i < [typeDict count]; i++){
NSString *val = [typeDict objectForKey:[sortedKeys objectAtIndex:counter]];
NSString *thekey = [sortedKeys objectAtIndex:counter];
[sortedTypeDict setObject:val forKey:thekey];
counter++;
}
NSLog(#"\n\nsorted dict: %#", sortedTypeDict);
Not a big deal!
If any value from the dictionary is null then use this code
NSArray *keys = [typeDict allKeys];
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES];
NSArray *sortedKeys = [keys sortedArrayUsingDescriptors:#[sd]];
NSLog(#"SORT 1 %#",sortedKeys);
NSMutableDictionary *sortedTypeDict = [NSMutableDictionary dictionary];
int counter = 0;
for(int i=0; i < [typeDict count]; i++){
id val = [typeDict objectForKey:[sortedKeys objectAtIndex:counter]];
NSString *thekey = [sortedKeys objectAtIndex:counter];
[sortedTypeDict setObject:val forKey:thekey];
counter++;
}
NSLog(#"\n\nsorted dict: %#", sortedTypeDict);

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:)];

How can I retrieve all the contents of an NSDictionary?

I want to select and retrieve all the contents from an NSDictionary. I have a structure like this
- (void)viewDidLoad {
[super viewDidLoad];
listaOggetti = [[NSMutableArray alloc] init];
NSArray *arrayOne = [NSArray arrayWithObjects: #"First",#"Second",#"Third", nil];
NSArray *sortedOne = [arrayOne sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictOne = [NSDictionary dictionaryWithObject:sortedOne forKey:#"Elementi"];
NSArray *arrayTWo = [NSArray arrayWithObjects:#"First1",#"Second1" ..., nil];
NSArray *sortedTwo = [arrayTwo sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictTwo = [NSDictionary dictionaryWithObject:sortedTWo forKey:#"Elementi"];
NSArray *arrayThree = [NSArray arrayWithObjects:#"First2",#"Second2" ... , nil];
NSArray *sortedThree = [arrayThree sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictThree = [NSDictionary dictionaryWithObject:sortedThree forKey:#"Elementi"];
[listaOggetti addObject:dictOne];
[listaOggetti addObject:dictTwo];
[listaOggetti addObject:dictThree];
}
And I want to retrieve all the objects for the key #"Elementi" (should be around 45) in order to add them in another array, like:
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
NSArray *array = [dict objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row] ;
(With this, dict is only 9 objects filled in my project).
At the end, the *array should be around 45 objects filled. I tried with allValues, but didn't work.
How can I fix it?
The easiest is to do this in -viewDidLoad:
NSMutableArray *allObjects = [[NSMutableArray alloc] init];
[allObjects addObjectsFromArray:sortedOne];
[allObjects addObjectsFromArray:sortedTwo];
[allObjects addObjectsFromArray:sortedThree];
Alternately, you can get them from the dictionaries in a similar fashion:
NSMutableArray *allObjects = [[NSMutableArray alloc] init];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:0] objectForKey#"Elementi"];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:1] objectForKey#"Elementi"];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:2] objectForKey#"Elementi"];
What you are failing to understand is that listaOggetti is an NSMutableArray containing three objects. When you call
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
the result is that dict is a single dictionary, one of the three objects in listaOggetti. Therefore when you call
NSArray *array = [dict objectForKey:#"Elementi"];
the result is that array is the object for the key #"Elementi" of that one single dictionary dict. Your code makes no attempt to combine the three DIFFERENT dictionaries or to combine the three arrays, each set as objectForKey:#"Elementi" for the three DIFFERENT dictionaries.
If you want one array that is the concatenation of all three different arrays, then use one of the snippets provided above. In both of these snippets, the result is that allObjects is an NSMutableArray containing all three arrays, in order.