sortUsingSelector未排序NSStrings数组

时间:2010-02-05 06:04:14

标签: objective-c macos sorting nsmutablearray

这让我感到困惑。我有一个功能:

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

}

在第一个for循环中找到输出NSStrings,如下所示:

  

LOCATION1

     

LOCATION2

     

不是位置

     

LOCATION2

     

LOCATION3

     

LOCATION2

我希望输出按字母顺序排列:

  

LOCATION1

     

LOCATION2

     

LOCATION2

     

LOCATION2

     

LOCATION3

     

不是位置

但是,无论如何,“[SortedArray sortUsingSelector:@selector(compare :)];”只是不排序数组。什么都没发生。

也许我说这一切都错了,但我在网上看到的每个例子都像这样对NSStrings进行排序 - 所以我不知道该怎么办。

我的最后阶段,如果有更好的解决方案,那么输出最大重复输入的计数。我在想排序是朝这个方向迈出的一步。

真的,我正在寻找的是输出:

  

LOCATION2

因为“location2”在该列表中的重复次数最多。

任何帮助?

5 个答案:

答案 0 :(得分:8)

鉴于您的字符串数组如下所示:

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 :(得分:1)

首先,你疯狂地泄露记忆。学习规则:如果你创建一个对象(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];
}

您不需要释放ReadStoredArraySortedArray,因为您不拥有它们(在调用中没有alloc / init或copy)。

至于你的实际问题......代码没有明显的原因,为什么排序不起作用。抱歉!很多常见问题都会引发异常,而不是无声的失败。

如果文件不存在或无法加载,initWithContentsOfFile:会抛出异常。如果ReadStoredArray为零,那么CurrentResult将为零,addObject:将引发异常。如果数组中的对象没有响应compare:选择器,sortUsingSelector:会抛出异常。如果SortedArray为nil,则代码将无声地失败,但它也不会输出任何输出。 (另外,因为它是nil,alloc / init必须失败,这意味着你的内存不足。)

除了内存泄漏和非传统风格(用大写字母开始你的变量名),你的代码没有任何明显的错误。有些东西不见了。

答案 2 :(得分:1)

您可以使用API​​轻松对数组进行排序:

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

在此语句之后,您只需打印数组对象,即可获得已排序的数组。

答案 3 :(得分:0)

我没有看到任何明显会阻止你的数组排序的东西,所以我会尝试使用自定义的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

答案 4 :(得分:0)

排序数组的一个小问题是你必须查看在排序过程中是否返回了一个数组。如果忽略捕获返回的数组,则可能看起来数组未被排序。它可能是,但是如果没有数组可以捕获它,它将会再次消失。

相关问题