This question already has answers here:
How to do a natural sort on an NSArray?
(5 answers)
Closed 6 years ago.
How to sort an NSMutableArray numerically when it contains objects like follows:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"P3",#"P1",#"P4",#"P10", nil];
The output of the same should be like: P1, P3, P4, P10
You need to use NSNumericSearch
[array sortUsingComparator:^NSComparisonResult(NSString* _Nonnull str1, NSString* _Nonnull str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
From the Header Documentation-
NSNumericSearch = 64, /* Added in 10.2; Numbers within strings are compared using numeric value, that is, Foo2.txt < Foo7.txt < Foo25.txt; only applies to compare methods, not find */
Hope this is what you are looking for.
Assuming there is always a character at the start of the strings, then:
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSInteger i1 = [[obj1 substringFromIndex:1] integerValue];
NSInteger i2 = [[obj2 substringFromIndex:1] integerValue];
if (i1 > i2)
return NSOrderedDescending;
else if (i1 < i2)
return NSOrderedAscending;
return NSOrderedSame;
}];
try this code:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"P3",#"P1",#"P4",#"P10", nil];
NSLog(#"Array: %#",array);
NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:#selector(localizedStandardCompare:)];
NSArray *sorters = [[NSArray alloc] initWithObjects:lastNameDescriptor, nil];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:sorters];
NSMutableArray *sortArray = [[NSMutableArray alloc] init];
[sortArray addObjectsFromArray:sortedArray];
NSLog(#"sortArray : %#",sortArray);
Output::
2016-06-15 16:47:47.707 test[5283:150858] Array: (
P3,
P1,
P4,
P10
)
2016-06-15 16:47:47.708 test[5283:150858] sortArray : (
P1,
P3,
P4,
P10
)
You can also sort NSArrayor NSMutableArray using NSSortDescriptor.
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:YES];
NSArray *sortedArray = [<arrayToBeSorted> sortedArrayUsingDescriptors:#[sd]];
NSLog(#"Result = %#", sortedArray);
Related
I have an array of NSString, each NSString element contains a timestamp (epoch time) and other characters, e.g.: "time:1474437948687, <other characters>".
NSArrary *myData = [self loadData];// my array
So, myData looks like this inside:
{"time:1474437948687,fajlsfj...",
"time:1474237943221, axsasdfd...",
"time:1474681430940, someother...",
...
}
I need to have an array which contains the same elements as the above array, but are sorted in descending order of the timestamp. How can I do it?
I get stuck with iterating over the array of NSString:
for (NSString element in myData) {
...
}
Use following sortedArrayUsingComparator it will work for me : I use static data e.g time:1474437948687, ..
**time:1474437948687, <other characters> Consider String Format..**
NSArrary *myData = [self loadData];
NSArrary *sortedmyData = [[myData sortedArrayUsingComparator: ^(id obj1, id obj2) {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
// Change Date formate accordingly ====
[df setDateFormat:#"dd-MM-yyyy"];
NSDate *d1 = [df dateFromString:[self sperateDate:obj1]];
NSDate *d2 = [df dateFromString:[self sperateDate:obj2]];
return [d1 compare: d2];
}];
// This is function is developed as per time:1474437948687, Consider String Format..
- (NSString *)sperateDate : (NSString *)obj1 {
NSArray *arr = [obj1 componentsSeparatedByString:#","];
NSArray *arr1 = [arr[0] componentsSeparatedByString:#":"];
return arr1[1];
}
Update Compare with primitive type :
NSArray *myData = #[#"time:1474437948687,fajlsfj...",#"time:1474237943221, axsasdfd...",#"time:1474681430940, someother..."
NSArray *sortedmyData = [myData sortedArrayUsingComparator: ^(id obj1, id obj2) {
NSNumber *d1 = [NSNumber numberWithDouble:[[self sperateDate:obj1] doubleValue]];
NSNumber *d2 = [NSNumber numberWithDouble:[[self sperateDate:obj2] doubleValue]];
return [d1 compare: d2];
}];
Hope this help you...
Do let me know if you have any other query
Try this :
NSArray *timearray = #[#"time:1474437948687,fajlsfj...",
#"time:1474237943221, axsasdfd...",
#"time:1474681430940, someother..."];
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#""
ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [timearray sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sortedArray %#",sortedArray);
Output:
sortedArray (
"time:1474681430940, someother...",
"time:1474437948687,fajlsfj...",
"time:1474237943221, axsasdfd..."
)
First of all it seems to be a good idea to transform the string into instances of an entity type that reflects the data in a key-value manner. Then you can sort it easily by using an instance of NSSortDescriptor:
NSSortDescriptor *timeSorter = [NSSortDescriptor sortDescriptorWithKey:#"time" ascending:NO];
NSArray *sorted = [myData sortedArrayUsingSortDescriptors:#[timeSorter]];
However, you can sort the array as is by using a more complex sort descriptor:
NSSortDescriptor *timeSorter = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO comparator:
^(id one, id two )
{
NSString *timestamp1 = [one compenentsSepartedByString:#","][0];
timestamp1 = [timestamp1 substringFromIndex:5];
NSString *timestamp2 = [two compenentsSepartedByString:#","][0];
timestamp2 = [timestamp2 substringFromIndex:5];
return [timestamp1 compare:timestamp2 options:NSNumericSearch range:NSMakeRange(0, [timestamp1 length])];
}];
NSArray *sorted = [myData sortedArrayUsingSortDescriptors:#[timeSorter]];
Typed in Safari.
NSArray A = #[[[#"id":#"3"]], [[#"id":#"4"]] ,[[#"id":#"c"]],[[#"id":#"f"]]];
NSArray idArray = #[#"c", #"3", #"4",#"f"];
Just a example I assumed.
How can I sort A by its id with idArray?
That is, I want A to become:
NSArray A= #[[[#"id":#"c"]], [[#"id":#"3"]] ,[[#"id":#"4"]],[[#"id":#"f"]]];
Now, I want to ask for an algorithm to sort array A to get the desired result.
---I get my answer when I search in google:
NSArray *sorter = #[#"B", #"C", #"E"];
NSMutableArray *sortee = [#[
#[#"B", #"abc"],
#[#"E", #"pqr"],
#[#"C", #"xyz"]
] mutableCopy];
[sortee sortUsingComparator:^(id o1, id o2) {
NSString *s1 = [o1 objectAtIndex:0];
NSString *s2 = [o2 objectAtIndex:0];
NSInteger idx1 = [sorter indexOfObject:s1];
NSInteger idx2 = [sorter indexOfObject:s2];
return idx1 - idx2;
}];
If you want to compare both array you can use
NSArray *array1=#[#"3",#"4",#"c","f"];
NSArray *array2=#[#"c",#"3",#"4","f"];
array1=[array1 sortedArrayUsingSelector:#selector(compare:)];
array2=[array2 sortedArrayUsingSelector:#selector(compare:)];
if ([array1 isEqualToArray:array2]) {
NSLog(#"both are same");
}
else{
NSLog(#"both are differnt");
}
or If you want to get common elements from 2 array use
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets
NSArray* result = [set1 allObjects];
This would be a better way to make a dictionary for A. And then sorting based on their specific values like IQ, Name etc.
NSArray A = #[[[#"id":#"3"]], [[#"id":#"4"]] ,[[#"id":#"c"]],[[#"id":#"f"]]];
NSArray idArray = #[#"c", #"3", #"4",#"f"];
NSMutableArray *array = [NSMutableArray array];
for (int id = 0;idx<[A count];id++) {
NSDictionary *dict = #{#"Name": A[id],#"IQ":idArray[id]};
[array addObject:dict];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"IQ" ascending:NO];
[array sortUsingDescriptors:#[descriptor]]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I need to sort alphabetic data in a table view and ignore numbers, like :
- 123 test
- 939 urne
- 403 vase
Currently, data is loaded like this:
- 939 urne
- 123 test
- 403 vase
What's the best choice for ignoring numbers?
You can store data separately in dictionaries, like,
Array
(
{
"number" = 403
"text" = "vase"
},
{
"number" = 403
"text" = "vase"
}
)
then you can sort using,
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey:#"text" ascending:YES];
[array sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
The best Way to this
NSSortDescriptor *descriptor; = [NSSortDescriptor sortDescriptorWithKey:#"text" ascending:YES comparator:^(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2 :NSCaseInsensitiveSearch];
}];
[arrDocuments sortUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
Now start a loop which has all the objects in the array that you wish to sort. Suppose the name of the array is originalArray.
NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSMutableArray *finalArray = [[NSMutableArray alloc] init];
for(int i = 0; i < originalArray.count; i++)
{
NSString *tempstr = [originalArray objectAtIndex:i]; // suppose it is 123 - abcd
NSString *newString = [[tempstr componentsSeparatedByCharactersInSet: [[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:#""];
NSDictionary *dict = [[NSDictionary alloc] init];
[dict setValue:#(i) forKey:#"num"];
[dict setValue:newString forKey:#"char"];
[newArray addObject:dict];
}
Now you can sort newArray:-
NSSortDescriptor * descriptor = [NSSortDescriptor sortDescriptorWithKey:#"char" ascending:YES];
[newArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
Now you can get the indexes from the dictionaries present in this array(under key num)
for(int j = 0; j<newArray.count ; j++)
{
NSDictionary *dict1 = [[NSDictionary alloc] init];
dict1 = [newArray objectAtIndex: j];
int number = [[dict1 objectForKey:#"num"] intValue];
NSString *str = [originalArray objectAtIndex:number];
//Now add this string in the finalArray.
[finalArray addObject:str];
}
I hope you were able to understand this. :)
So I have an array of custom "Element" objects (hey hold atomic number, chemical symbol, atomic mass, etc...) and I am having trouble sorting them by one of their properties;
Here is the code:
switch (sortDescriptor) {
case 0: {
//Sort the array by "ATOMIC NUMBER"
NSArray *sortedArray = [self.elementsArray sortedArrayUsingComparator:^(id a, id b) {
NSNumber *first = #([(SAMElement *)a atomicNumber]);
NSNumber *second = #([(SAMElement *)b atomicNumber]);
return [first compare:second];
}];
self.elementsArray = [sortedArray mutableCopy];
}
case 1: {
//Sort the array by "ELEMENT NAME"
NSArray *sortedArray = [self.elementsArray sortedArrayUsingComparator:^(id a, id b) {
NSString *first = [(SAMElement *)a elementName];
NSString *second = [(SAMElement *)b elementName];
return [first compare:second];
}];
self.elementsArray = [sortedArray mutableCopy];
}
case 2:{
NSLog(#"sorting by chemical symbol");
//Sort the array by "CHEMICAL SYMBOL"
NSArray *sortedArray = [self.elementsArray sortedArrayUsingComparator:^(id a, id b) {
NSString *first = [(SAMElement *)a chemichalSymbol];
NSString *second = [(SAMElement *)b chemichalSymbol];
return [first compare:second];
}];
self.elementsArray = [sortedArray mutableCopy];
}
case 3: {
//Sort the array by "ATOMIC MASS"
NSArray *sortedArray = [self.elementsArray sortedArrayUsingComparator:^(id a, id b) {
NSNumber *first = [(SAMElement *)a atomicMass];
NSNumber *second = [(SAMElement *)b atomicMass];
return [first compare:second];
}];
self.elementsArray = [sortedArray mutableCopy];
}
default:
break;
}
When is sorts it returns a totally random list of elements. Am i doing something wrong?
The best way to sort an array of objects by some property of the object, its using NSSortDescriptor. In initWithKey, you can set the name of the property that you want to sort.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"atomicNumber" ascending:NO];
[self.elementsArray sortUsingDescriptors:#[sortDescriptor]];
In your case, just copy this code above in each case section of your switch statement, changing the key for #"elementName" and #"chemichalSymbol".
You can change the ascending value from NO to YES, depending what type of order do you want.
Please, let me know if worked or not.
I'm not seeing the bug immediately, but you're reinventing the wheel here. The correct tool for this is sortedArrayUsingDescriptors:
[self.elementsArray sortedArrayUsingDescriptors:#[
[NSSortDescriptor alloc] initWithKey:#"atomicNumber"] ascending:YES]
]];
Try that and see if it gets rid of your bug. If you're getting random orders, that usually suggests that your comparitor is inconsistent (sometimes A>B and sometimes B>A for the same A&B).
I have an NSMutableDictionary that maps NSString to NSString (although the values are NSStrings, they are really just integers).
For example consider the following mappings,
"dog" --> "4"
"cat" --> "3"
"turtle" --> "6"
I'd like to end up with the top 10 entries in the dictionary sorted by decreasing order of the value. Can someone show me code for this? Perhaps there is an array of keys and another array of values. However it is, I don't mind. I'm just trying to have it be efficient.
Thank you!
Get the Array of the Values, sort that array and then get the key corresponding to the value.
You can get the values with:
NSArray* values = [myDict allValues];
NSArray* sortedValues = [values sortedArrayUsingSelector:#selector(comparator)];
But, if the collection is as you show in your example, (I mean, you can infer the value from the key), you can always sort the keys instead messing with the values.
Using:
NSArray* sortedKeys = [myDict keysSortedByValueUsingSelector:#selector(comparator)];
The comparator is a message selector which is sent to the object you want to order.
If you want to order strings, then you should use a NSString comparator.
The NSString comparators are i.e.: caseInsensitiveCompare or localizedCaseInsensitiveCompare:.
If none of these are valid for you, you can call your own comparator function
[values sortedArrayUsingFunction:comparatorFunction context:nil]
Being comparatorFunction (from AppleDocumentation)
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
The simplest way is:
NSArray *sortedValues = [[yourDictionary allValues] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSMutableDictionary *orderedDictionary=[[NSMutableDictionary alloc]init];
for(NSString *valor in sortedValues){
for(NSString *clave in [yourDictionary allKeys]){
if ([valor isEqualToString:[yourDictionary valueForKey:clave]]) {
[orderedDictionary setValue:valor forKey:clave];
}
}
}
Use this method:
- (NSArray *)sortKeysByIntValue:(NSDictionary *)dictionary {
NSArray *sortedKeys = [dictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) {
int v1 = [obj1 intValue];
int v2 = [obj2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}];
return sortedKeys;
}
Call it and then create a new dictionary with keys sorted by value:
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
#"4", #"dog",
#"3", #"cat",
#"6", #"turtle",
nil];
NSArray *sortedKeys = [self sortKeysByIntValue:dictionary];
NSMutableDictionary *sortedDictionary = [[NSMutableDictionary alloc] init];
for (NSString *key in sortedKeys){
[sortedDictionary setObject:dictionary[key] forKey:key];
}
Sorting the keys and using that to populate an array with the values:
NSArray *keys = [dict allKeys];
NSArray *sKeys = [keys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableArray *sValues = [[[NSMutableArray alloc] init] autorelease];
for(id k in sKeys) {
id val = [dict objectForKey:k];
[sValues addObject:val];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"interest" ascending:YES];
[unsortedArray sortUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
recentSortedArray = [stories copy];
if you want to sort data in ascending order for key 'name' for such kind of Example then this may help you.
arrayAnimalList = [
{
'name' = Dog,
'animal_id' = 001
},
{
'name' = Rat,
'animal_id' = 002
},
{
'name' = Cat,
'animal_id' = 003
}
];
This is a code which help you to get sorted array
//here you have to pass key for which you want to sort data
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor];
// here you will get sorted array in 'sortedArray'
NSMutableArray * sortedArray = [[arrayAnimalList sortedArrayUsingDescriptors:sortDescriptors] mutableCopy];