sortUsingSelector Не сортирует массив NSStrings - PullRequest
4 голосов
/ 05 февраля 2010

Это смущает меня. У меня есть функция, которая делает это:

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

}

, который находит выходные строки NSStrings в первом цикле for следующим образом:

Location1

LOCATION2

Не место

LOCATION2

Location3

LOCATION2

и я хочу, чтобы вывод был в алфавитном порядке:

Location1

LOCATION2

LOCATION2

LOCATION2

Location3

Не место

Но, несмотря ни на что, "[SortedArray sortUsingSelector: @selector (сравни :)];" просто не сортирует массив. Ничего не произошло.

Может быть, я все делаю неправильно, но каждый пример, который я видел в Интернете, сортирует строки NSS вот так - поэтому я не знаю, что делать.

Мой эндшпиль, если есть лучшее решение, это вывести количество наибольшей повторной записи. Я думал, что сортировка станет шагом в этом направлении.

Действительно, что я ищу, так это вывод:

LOCATION2

Потому что "location2" имеет наибольшее количество повторений в этом списке.

Любая помощь?

Ответы [ 5 ]

8 голосов
/ 05 февраля 2010

Учитывая, что ваш массив строк выглядит так:

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

Вы можете отсортировать это так:

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

Выход:

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

Если вы хотите найти объект с наибольшим количеством вхождений, учитывая исходный массив:

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

Выход:

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
1 голос
/ 14 августа 2010

Вы можете легко отсортировать массив с помощью API:

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

После этого утверждения вы просто распечатываете объекты массива, вы получите отсортированный массив.

1 голос
/ 05 февраля 2010

Для начала, вы теряете память как сумасшедший. Изучите правила: если вы создаете объект (alloc / init или copy), то вы являетесь его владельцем и должны освободить его.

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

В этой строке вы создаете изменяемый словарь, затем создаете изменчивую его копию, теряя исходный экземпляр. Вы должны заменить это на:

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

Вы фактически не изменяете словарь в своем коде, поэтому я позволю ему быть NSDictionary.

Далее введите в этом объявлении:

NSMutableArray *ReadStoredArray = [item objectForKey:SearchTerm];

неверно. Даже если словарь изменчив, его члены не гарантированы. (mutableCopy является мелкой копией.) Поскольку вы фактически не изменяете этот массив, давайте изменим строку на:

NSArray *ReadStoredArray = [item objectForKey:SearchTerm];

Теперь, если вы хотите скопировать элементы из ReadStoredArray в SortedArray, вы можете заменить цикл на

[SortedArray addObjectsFromArray:ReadStoredArray];

Но поскольку вы делаете точную копию, вы также можете просто написать

SortedArray = [ReadStoredArray mutableCopy];

Но вам не нужно, чтобы SortedArray был изменяемым, поэтому вы можете просто вызвать эту другую форму, которая возвращает новый отсортированный массив, а не сортировать изменяемый массив на месте:

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

Итак, теперь ваша функция выглядит так:

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];
}

Вам не нужно освобождать ReadStoredArray или SortedArray, потому что вы не являетесь их владельцем (нет alloc / init или копирования в вызовах).

Что касается вашего фактического вопроса ... в коде нет очевидной причины, по которой сортировка не будет работать. Сожалею! Многие распространенные проблемы вызвали бы исключения, а не тихие сбои.

Если файл не существует или не может быть загружен, initWithContentsOfFile: вызвало бы исключение. Если ReadStoredArray равно нулю, то CurrentResult будет равно нулю, а addObject: выдаст исключение. Если бы объекты в массиве не отвечали на селектор compare:, sortUsingSelector: вызвало бы исключение. Если бы SortedArray было равно нулю, код молча потерпел бы неудачу, но он также не выводил бы выходные данные. (Кроме того, для того, чтобы он был равен нулю, alloc / init должен был потерпеть неудачу, что означает, что у вас недостаточно памяти.)

Помимо утечек памяти и нетрадиционного стиля (начиная с имен переменных в верхнем регистре), в вашем коде нет ничего плохого. Чего-то не хватает.

0 голосов
/ 29 ноября 2013

Одна небольшая проблема с сортировочными массивами заключается в том, что вам нужно посмотреть, возвращается ли массив в процессе сортировки. Если вы забыли перехватить возвращенный массив, может показаться, что массив не сортируется. Вероятно, так и есть, но как только массив не сможет его перехватить, он снова исчезнет.

0 голосов
/ 05 февраля 2010

Я не видел ничего очевидного, что могло бы помешать сортировке массива, поэтому я бы попытался использовать собственный метод myCompare: в качестве селектора сортировки вместо встроенного сравнения. Это позволит вам регистрировать каждое отдельное сравнение, чтобы вы знали, что каждый объект сравнивается, как следует, и возвращает правильный результат сравнения.

Добавьте это в свой файл (выше определения функции), затем измените свою функцию для сортировки с помощью @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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...