SortUsingSelector Not sorting an NSStrings array

It bothers me. I have a function that does this:

void ListAllStoredLocations(NSString *SearchTerm){ NSMutableDictionary *item; NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/Preferences/yourprogram.plist"]; item = [[[NSMutableDictionary alloc] initWithContentsOfFile:filePath] mutableCopy]; NSMutableArray *ReadStoredArray = [item objectForKey:SearchTerm]; NSMutableArray *SortedArray = [[NSMutableArray alloc] init]; NSString * CurrentResult=@ ""; for (int i = 0; i< [ReadStoredArray count]; i++){ CurrentResult=(NSString *)[ReadStoredArray objectAtIndex:i]; [SortedArray addObject:CurrentResult]; } [SortedArray sortUsingSelector:@selector(compare:)]; for (int i = 0; i< [SortedArray count]; i++){ NSLog(@"%@",[SortedArray objectAtIndex:i]); } [item release]; 

}

Which finds the NSStrings outputs in the first for the loop as follows:

LOCATION1

LOCATION2

Not location

LOCATION2

Location3

LOCATION2

and I want the result to be in alphabetical order:

LOCATION1

LOCATION2

LOCATION2

LOCATION2

Location3

Not location

But, in spite of everything, "[SortedArray sortUsingSelector: @selector (compare :)];" just doesn't sort the array. Nothing happened.

Maybe I profess everything, but every example I saw on the Internet sorts NSStrings like this, so I don’t know what to do.

My endgame, if there is a better solution, I need to display the counter of the largest recurring record. I thought sorting would be a step in that direction.

Indeed, what I'm looking for is the result:

LOCATION2

Because "location2" has the most duplicates on this list.

Any help?

+4
source share
5 answers

Given that your array of strings looks like this:

 NSMutableArray * array = [NSMutableArray array]; [array addObject:@"Location1"]; [array addObject:@"Location2"]; [array addObject:@"Not a location"]; [array addObject:@"Location2"]; [array addObject:@"Location3"]; [array addObject:@"Location2"]; NSLog(@"------------- original:"); for (id obj in array) NSLog(@"%@", obj); 

You can sort it as follows:

 NSLog(@"------------- sorted:"); NSArray * sortedArray = [array sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; for (id obj in sortedArray) NSLog(@"%@", obj); 

Conclusion:

 2010-02-06 00:24:14.915 x[23867:903] ------------- original: 2010-02-06 00:24:14.917 x[23867:903] Location1 2010-02-06 00:24:14.921 x[23867:903] Location2 2010-02-06 00:24:14.922 x[23867:903] Not a location 2010-02-06 00:24:14.922 x[23867:903] Location2 2010-02-06 00:24:14.923 x[23867:903] Location3 2010-02-06 00:24:14.924 x[23867:903] Location2 2010-02-06 00:24:14.924 x[23867:903] ------------- sorted: 2010-02-06 00:24:14.925 x[23867:903] Location1 2010-02-06 00:24:14.926 x[23867:903] Location2 2010-02-06 00:24:14.926 x[23867:903] Location2 2010-02-06 00:24:14.927 x[23867:903] Location2 2010-02-06 00:24:14.927 x[23867:903] Location3 2010-02-06 00:24:14.928 x[23867:903] Not a location 

If you want to find the object with the most occurrences, given the original array:

 NSCountedSet * set = [[NSCountedSet alloc] initWithArray:array]; for (id obj in set) NSLog(@"%d - %@", [set countForObject:obj], obj); int count = 0; int maxc = 0; id maxobj; for (id obj in set) { count = [set countForObject:obj]; if (maxc < count) maxc = count, maxobj = obj; } NSLog(@"max is: %d - %@", maxc, maxobj); 

Conclusion:

 2010-02-06 00:39:46.310 x[24516:903] 1 - Location1 2010-02-06 00:39:46.311 x[24516:903] 1 - Not a location 2010-02-06 00:39:46.311 x[24516:903] 3 - Location2 2010-02-06 00:39:46.312 x[24516:903] 1 - Location3 2010-02-06 00:39:46.313 x[24516:903] max is: 3 - Location2 
+8
source

To start, you lose your memory like crazy. Learn the rules: if you create an object (alloc / init or copy), you own it and must free it.

 item = [[[NSMutableDictionary alloc] initWithContentsOfFile:filePath] mutableCopy]; 

On this line, you create a mutable dictionary, and then create a mutable copy, losing the original instance. You should replace this as follows:

 item = [[NSDictionary alloc] initWithContentsOfFile:filePath]; 

In fact, you do not modify the dictionary in your code, so I assume it is NSDictionary.

Next, the type of this declaration:

 NSMutableArray *ReadStoredArray = [item objectForKey:SearchTerm]; 

wrong. Even if the dictionary was changed, its members are not guaranteed. ( mutableCopy is a shallow copy.) Since you are not actually mutableCopy this array, change the line to:

 NSArray *ReadStoredArray = [item objectForKey:SearchTerm]; 

Now, if you want to copy elements from ReadStoredArray to SortedArray, you can replace the loop with

 [SortedArray addObjectsFromArray:ReadStoredArray]; 

But since you are making an exact copy, you can also just write

 SortedArray = [ReadStoredArray mutableCopy]; 

But you don't need the SortedArray change, so you can just call this other form, which returns a new sorted array, rather than sorting the changed array in place:

 SortedArray = [ReadStoredArray sortedArrayUsingSelector:@selector(compare:)]; 

So now your function looks like this:

 void ListAllStoredLocations(NSString *SearchTerm) { NSDictionary *item; NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/Preferences/yourprogram.plist"]; item = [[NSDictionary alloc] initWithContentsOfFile:filePath]; NSArray *ReadStoredArray = [item objectForKey:SearchTerm]; NSArray *SortedArray = [ReadStoredArray sortedArrayUsingSelector:@selector(compare:)]; for (int i = 0; i< [SortedArray count]; i++){ NSLog(@"%@",[SortedArray objectAtIndex:i]); } [item release]; } 

You do not need to issue ReadStoredArray or SortedArray because you do not own them (no / init or copy is highlighted in calls).

As for your actual question ... there is no obvious reason from the code why sorting will not work. Sorry Many common problems would cause exceptions rather than silence.

If the file does not exist or cannot be loaded, initWithContentsOfFile: would throw an exception. If ReadStoredArray was nil, then CurrentResult would be nil, and addObject: would throw an exception. If the objects in the array did not respond to the compare: selector, sortUsingSelector: would throw an exception. If the SortedArray was zero, the code will fail, but it will also not output the result. (Also, in order for this to be nil, alloc / init would have to fail, meaning you did not have enough memory.)

Besides the memory leaks and the unconventional style (starting your variable names with lowercase letters), there is nothing wrong with the code. Something is missing.

+1
source

You can easily sort the array using the API:

 [YourArrayObj sortUsingSelector:@selector(compare:)]; 

After this statement, you simply print out the array objects, you get a sorted array.

+1
source

I don’t see anything obvious to prevent your array from sorting, so I would like to try using custom myCompare: A way to sort the selector instead of the inline comparison. This will allow you to enter each individual comparison, so that you know, each object becomes compared as it should, and it returns the correct comparison result.

Add to this file (above the function definition), and then change the sort function with @selector (myCompare :)

 @interface NSString (MyCompare) - (NSComparisonResult) myCompare: (NSString *) aString; @end @implementation NSString (MyCompare) - (NSComparisonResult) myCompare: (NSString *) aString { NSComparisonResult result; result = [self compare: aString]; NSLog(@"Compared %@ & %@, result: %d", self, aString, (int) result); return result; } @end 
0
source

One small mistake with sorting arrays is that you need to see if the array is returned during the sorting process. If you neglect the capture of the returned array, it might seem that the array is not sorted. This is probably true, but as soon as this happens, if there is no array to catch it, it will disappear again.

0
source

Source: https://habr.com/ru/post/1300372/