How to sort multi-dimensional array in objective-c? - iphone

I'm having a two dimensional array as follows
NSArray *cities = [NSArray arrayWithObjects:#"New Delhi",#"Karachi",#"Dhaka",#"Columbu", nil];
NSArray *distance = [NSArray arrayWithObjects:#"500",#"1400",#"1200",#"2800", nil];
NSMutableArray *details= [[NSMutableArray alloc]initWithCapacity:cities.count];
[details addObject:cities];
[details addObject:distance];
Now, the details array looks like
(
(
"New Delhi",
Karachi,
Dhaka,
Columbu
),
(
500,
1400,
1200,
2800
)
)
I need to sort the array with ascending order w.r.t distance array
ie,
(
(
"New Delhi",
Dhaka,
Karachi,
Columbu
),
(
500,
1200,
1400,
2800
)
)
how to do this?
I also need to sort the whole array by alphabetical order w.r.t cities array.
I tried using sortUsingComparator but, can't get the solution completely.
Any help would be appreciated.

self.arrayForRows = [[NSMutableArray alloc]init];
NSMutableArray *arrayForCities = [[NSMutableArray alloc]initWithObjects:#"Mumbai",#"Vizag",#"Hyderabad",#"Ahemdabad",#"Secunderabad", nil];
NSMutableArray *arrayForDistance = [[NSMutableArray alloc]initWithObjects:#"200",#"320",#"32",#"450",#"14", nil];
for (int i=0; i<arrayForCities.count; i++)
{
NSMutableDictionary *tempDicts = [[NSMutableDictionary alloc]init];
[tempDicts setObject:[arrayForCities objectAtIndex:i] forKey:#"names"];
[tempDicts setObject:[NSNumber numberWithInt:[[arrayForDistance objectAtIndex:i] intValue]] forKey:#"distance"];
[self.arrayForRows addObject:tempDicts];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:YES];
[self.arrayForRows sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

Structure is complicated. Make a class city containing name and distance. Then add objects of this class. Then you can sort using city.distance.

Related

Sort an array using array index

I am stuck here......
I have two arrays Arr_title and Arr_distance
I get sorted Arr_distance using this method
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES]autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
but problem is that i want to sort Arr_title according to index of sortedFloats array...
thx in advance for help me..........
Try this,
NSDictionary *dict = [NSDictionary dictionaryWithObjects:Arr_title forKeys:Arr_distance];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES] autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
NSMutableArray *sortedTitles = [NSMutableArray array];
for (NSString *key in sortedFloats) {//or just use sortedTitles = [dict objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
[sortedTitles addObject:[dict valueForKey:key]];
}
NSLog(#"%#",sortedValues);
sortedTitles should give you the array sorted in the same order as sortedFloats.
hey instead of taking two different array take 1 dictionary with key title,distance save that dictionary in array then sort that array So you have got combination together so there is no any problem due to mapping in any sort(by title & by distance).
if i understand your question right , you can use NSDictionary for the same task
NSMutableArray *array = [NSMutableArray arrayWithArray:#[ #{#"title" : #"City1",#"dist" : #5},
# {#"title" : #"City2",#"dist" : #2.3 },
#{#"title" : #"City3",#"dist" : #11.0 },
#{#"title" : #"City4",#"dist" : #1.0},
#{#"title" : #"City5",#"dist" : #.5},
#{#"title" : #"City6",#"dist" : #13 }]];
NSLog(#"dict<%#>",array);
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"dist" ascending:YES];
NSArray *sortarray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSLog(#"sort array = <%#>",sortarray);
I got the solution see following code.........
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES]autorelease];
sortedFloats = [appDel.Arr_distance sortedArrayUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
NSLog(#" Sorted Array : %#", sortedFloats);
NSDictionary *dictTitle = [NSDictionary dictionaryWithObjects:Arr_title forKeys:appDel.Arr_distance];
// Sort the second array based on the sorted first array
sortedTitle = [dictTitle objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
NSLog(#" Sorted Title : %#",sortedTitle);
// Put the two arrays into a dictionary as keys and values
NSDictionary *dictAddress = [NSDictionary dictionaryWithObjects:Arr_address forKeys:appDel.Arr_distance];
// Sort the second array based on the sorted first array
sortedAddress = [dictAddress objectsForKeys:sortedFloats notFoundMarker:[NSNull null]];
NSLog(#" Sorted Address : %#",sortedAddress);
Dont forgot to retain your arrays if use in another method ....

Sorting two NSMutableArrays by 'nearest distance' first

I have two arrays, both full of NSString objects like this:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
How can I sort both arrays by the nearest distance first?
So the results would be like this:
titles = #"Title5", #"Title4", #"Title2", #"Title1", #"Title3"
distances = #"8.29", #"10.29", #"23.78", #"139.45", #"347.82"
I understand that NSSortDescriptor can be used in these circumstances but after looking through the documentation, I am still unsure about how.
I would sort the distances this way...
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSArray *sortedDistances = [listItem sortedArrayUsingComparator: ^(id a, id b) {
NSNumber *aNum = [f numberFromString:a];
NSNumber *bNum = [f numberFromString:b];
return [aNum compare:bNum];
}];
I can't think of a particularly quick way to get the associated titles sorted, but this should work ...
NSMutableArray *sortedTitles = [NSMutableArray array];
NSDictionary *distanceTitle = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
for (NSString *distance in sortedDistances) {
NSString *associatedTitle = [distanceTitle valueForKey:distance];
[sortedTitles addObject:associatedTitle];
}
You can use an NSComparator block and use NSArray's sortedArrayUsingComparator method. On that block, you will receive two objects to compare, and base on the comparison result, you can use NSMutableArray exchangeObjectAtIndex:withObjectAtIndex: method to change the values of titles.
Here is a sample how I sort an array of dictionaries by distance value:
-(void)reorderByDistance {
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
self.contentArray = [self.contentArray sortedArrayUsingDescriptors:sortDescriptors];
}
And my dictionary looks like this:
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"1", #"id", #"Business #1", #"name", #"This business does some pretty remarkable things", #"description", #"Alley Bar", #"category", #"1.2", #"distance", nil];
One approach would be to create a dictionary mapping titles to distances, sort the distances, and then iterate through the distances to recreate the titles:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
//Create a map of current titles to distances
NSDictionary *titleDistanceMap = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
//Need to sort the strings as numerical values
[distances sortUsingComparator:^(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//Now re-populate the titles array
[titles removeAllObjects];
for (NSString *distance in distances){
[titles addObject:[titleDistanceMap objectForKey:distance]];
}

Sorting mutable array by dictionary key

I have already looked through a few answers using the various sorting methods of NSMutableArray, but for some reason they are not working for me.
I am just trying to sort the mutable array which contains dictionaries by the Delay key within each dictionary. However, the "sorted" array is the exact same as the original array.
By the way, it works fine if I create a dummy mutable array and populate it with dictionaries containing numbers, but for some reason it won't sort this mutable array that I am initializing.
What am I doing wrong?
Here's my code:
playlistCalls = [[NSMutableArray alloc] initWithArray:[currentPlaylist objectForKey:#"Tunes"]];
NSLog(#"original %#", playlistCalls);
NSSortDescriptor *delay = [NSSortDescriptor sortDescriptorWithKey:#"Delay" ascending:YES];
[playlistCalls sortUsingDescriptors:[NSArray arrayWithObject:delay]];
NSLog(#"sorted %#", playlistCalls);
Here's the array containing the dictionaries:
2012-06-04 15:48:09.129 MyApp[57043:f503] original (
{
Name = Test Tune;
Delay = 120;
Volume = 100;
},
{
Name = Testes;
Delay = 180;
Volume = 100;
},
{
Name = Testing;
Delay = 60;
Volume = 100;
}
)
2012-06-04 15:48:09.129 MyApp[57043:f503] sorted (
{
Name = Test Tune;
Delay = 120;
Volume = 100;
},
{
Name = Testes;
Delay = 180;
Volume = 100;
},
{
Name = Testing;
Delay = 60;
Volume = 100;
}
)
The code above is fine when I use NSNumbers in my dictionary. That leads me to believe that the Delay value is stored as strings in your dictionary. What you will need to do then is sort by the strings integerValue.
NSSortDescriptor *delay =
[NSSortDescriptor sortDescriptorWithKey:#"Delay.integerValue" ascending:YES];
Please try the following, it worked with me
NSDictionary *dic;
NSMutableArray *arr = [[NSMutableArray alloc] init];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:120], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:160], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
dic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:100], #"Delay",
[NSNumber numberWithInt:100], #"Volume",
nil];
[arr addObject:dic];
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Delay" ascending:YES];
[arr sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];

How do I sort a NSMutableArray by NSString length?

I have a NSMutableArray containing NSStrings of various lengths. How would I go about sorting the array by the string length?
See my answer to sorting arrays with custom objects:
NSSortDescriptor *sortDesc= [[NSSortDescriptor alloc] initWithKey:#"length" ascending:YES];
[myArray sortUsingDescriptors:#[sortDesc]];
This is how I did it (love me some blocks!)
_objects = [matchingWords sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSNumber *alength = [NSNumber numberWithInt:((NSString*)a).length];
NSNumber *blength = [NSNumber numberWithInt:((NSString*)b).length];
return [alength compare:blength];
}];

Sort Array by Key

I have two arrays used in a small game.
If the player gets a score above a certain value their name & score gets output via
an UILabel.
NSArray *namesArray = [mainArray objectForKey:#"names"];
NSArray *highScoresArray = [mainArray objectForKey:#"scores"];
I need the UILabels to display with the highest score in descending order, with the corresponding name. I've used an NSSortDescriptor to sort the score values numerically.
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"self"
ascending:NO] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedScore = [[NSArray alloc]init];
sortedScore = [scoresArray sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *scoreLabels = [NSMutableArray arrayWithCapacity:10];
[scoreLabels addObject:scoreLabel1];
......
NSUInteger _index = 0;
for (NSNumber *_number in sortedScore) {
UILabel *_label = [scoreLabels objectAtIndex:_index];
_label.text = [NSString stringWithFormat:#"%d", [_number intValue]];
_index++;
}
This works well enough as the scores now display in descending order.
The problem is that I need the corresponding name to also display according in the new sorted order.
I cant use the same sort selector and I don't wont to sort them alphabetically, they need
to correspond to the name/score values that were first input.
Thanks in advance
You need to put the name and the score together into a single instance of NSDictionary, and then have an NSArray of those NSDictionary instances. Then when you sort by score, you can pull up the corresponding name.